How to set values of nested array of objects in mongodb - javascript

I have a data model which looks like this, so each documents has services array and each service contains an items array and I want to update properties in items array.
{
services: [
{
id: '1',
name: 'Service 01',
items: [
{
id: '1',
name: '',
qty: 10
},
{
id: '2',
name: '',
qty: 10
},
]
},
{
id: '2',
name: 'Service 02',
items: [
{
id: '3',
name: '',
qty: 10
},
{
id: '4',
name: '',
qty: 10
},
]
},
]
}
I want to set all the quantities inside services -> items to 0, What will be query for doing it I tried to do,
updateMany({}, { $set: { 'services.items.qty': 0 } });
but it's not working.
Let me know if you need more details.

the all positional operator $[] operator can be used to update all elements
playground
db.collection.update({},
{
$set: {
"services.$[].items.$[].qty": 0
}
})

Related

Merge array of objects preserving some key-values php

Consider the following two arrays:
[
{
id: jhz,
name: 'John',
eyes: 'Green',
description: 'Cool guy',
},
{
id: mbe,
name: 'Mary',
brand: 'M&B',
text: 'Something',
}
]
[
{
id: jhz,
name: 'John',
eyes: '',
},
{
id: mbe,
name: 'Mary',
},
{
id: 'beh',
name: 'Bernard',
}
]
First array may have any kind of key value pairs, but it will always have the key id and name. I want to merge the two arrays by taking id and name into account and preserving them, while merging everything else and replacing them with data from the first array if any keys duplicate.
Also tricky part - the merged array needs to follow the order of the second array.
So in this example the result I'm looking for is:
[
{
id: jhz,
name: 'John',
eyes: 'Green',
description: 'Cool guy',
},
{
id: mbe,
name: 'Mary',
brand: 'M&B',
text: 'Something',
},
{
id: 'beh',
name: 'Bernard',
}
]
you can do something like this using Array.map
const data1 = [{
id: 'jhz',
name: 'John',
eyes: 'Green',
description: 'Cool guy',
},
{
id: 'mbe',
name: 'Mary',
brand: 'M&B',
text: 'Something',
}
]
const data2 = [{
id: 'jhz',
name: 'John',
eyes: '',
},
{
id: 'mbe',
name: 'Mary',
},
{
id: 'beh',
name: 'Bernard',
}
]
const result = data2.map(d => ({...d, ...(data1.find(d1 => d1.id === d.id && d1.name === d.name) || {})}))
console.log(result)

How to restructure the JSON Object with existing key values?

I need to restructure the JSON object with existing key values, please check below input format of JSON
{
'Demo-1': [
{
sku: 'Brisk',
count: '2',
},
{
sku: 'Pepsi Cans',
count: '2',
},
{
sku: 'Pepsi Cans',
count: '4',
}
],
'Demo-2' :{
"A":[
{
sku: 'Mountain',
count: '4',
},
{
sku: 'Pepsi Bottles',
count: '4',
}
],
"B":[
{
sku: 'Lipton Dietgreentea',
count: '2',
},
{
sku: 'Lipton Dietgreentea Mixedberry',
count: '2',
}
]
}
}
In the above input JSON, the "Demo-1" have a single array of object and the second one has two array object.
I would like to change the above array, into like below
Result
{
'Demo-1': {
items: [{
sku: 'Brisk',
count: '2',
},
{
sku: 'Pepsi',
count: '2',
},
{
sku: 'Pepsi',
count: '4',
}
],
mode: "Veri",
istatus: "open"
},
'Demo-2': {
"items":{
"A" :[
{
sku: 'Mountain',
count: '4',
},
{
sku: 'Pepsi Bottles',
count: '4',
}
],
"B" :[
{
sku: 'Lipton Dietgreentea',
count: '2',
},
{
sku: 'Lipton Dietgreentea Mixedberry',
count: '2',
}]
},
mode: "Doubled",
istatus: "Closed"
}
}
I already using below code solution for partially achiving this
Object.fromEntries(
Object.entries(obj).map(
([key, items]) => [key, { items, mode: "verification", status: "open" }]
)
)
Now if the object has two array objects like Demo-2, the mode value should be "Doubled"
please help me out in resolving this.
Thanks in advance.
You need to add condition into your mapping function.
Proper condition depends on what possible items values may be.
If items always either array or { A, B } object, following condition is enough:
Object.fromEntries(
Object.entries(obj).map(
([key, items]) => [key, { items, mode: Array.isArray(items) ? 'Single' : 'Doubled', status: 'open' }]
)
)

Filter and Sort an Object Containing Array of Objects While Retaining Empty Arrays

I have an object I want to filter so that trainers with the most electric-type pokemon are listed first, but trainers without any electric-type pokemon are still present (represented as an empty array)
Here's my object:
obj = {
trainer1: [
{ name: 'pikachu', type: 'electric', id: 25 },
{ name: 'zapdos', type: 'electric', id: 145 },
{ name: 'psyduck', type: 'water', id: 54 },
],
trainer2: [
{ name: 'eevee', type: 'normal', id: 133 },
{ name: 'magmar', type: 'fire', id: 126 }
],
trainer3: [
{ name: 'ditto', type: 'normal', id: 132 },
{ name: 'magnemite', type: 'electric', id: 81 }
]
}
Becomes this object:
obj = {
trainer1: [
{ name: 'pikachu', type: 'electric', id: 25 },
{ name: 'zapdos', type: 'electric', id: 145 }
],
trainer3: [
{ name: 'magnemite', type: 'electric', id: 81 }
]
trainer2: [] // Array still present, but empty
}
I know reduce would come in handy here but I'm not sure how to set it up correctly.
This may be the bruteforce solution and there will be better solution than this but i think you can do it like the following way.
const tempArr = Object.keys(obj).map(key=>{
return {
key:key,
value:obj[key].filter(pokemon=>pokemon.type==='electric')
}
})
let newObj = {}
tempArr.sort((a,b)=>b.value.length-a.value.length)
tempArr.forEach(item=>{
newObj[item.key] = item.value
})
console.log(newObj)

How to remove duplicated item in array of array

I have an array like that:
[{
id: 1,
name: 'Proposal'
},
{
id: 2,
name: 'Contract',
children: [
{
name: 'Approval',
component: '/approval'
},
{
name: 'Cancellation',
component: '/cancellation'
}
]
}]
and another like that:
[{
id: 1,
name: 'Proposal'
},
{
id: 2,
name: 'Contract',
children: [
{
name: 'Approval',
component: '/approval'
}
]
},
{
id: 3,
name: 'Example'
}]
My question is how is the best way to filter arrays, and remove one if have duplicated or more, even in array of children. Or the best, is like arrays merge!

How to filter normalized nested JSON data with no array?

after use normalizr library I have the following normalized JSON object result in the Redux state of my application:
{
sports: {
byId: {
1: {
id: 1,
name: 'Soccer',
slug: 'soccer'
},
2: {
id: 2,
name: 'Basketball',
slug: 'basketball'
},
3: {
id: 3,
name: 'American Football',
slug: 'american-football'
}
},
allIds: [
'1',
'2',
'3'
]
},
competitions: {
byId: {
'1': {
id: 1,
name: 'Competition 1',
short_name: 'Comp 1',
slug: 'comp-1',
sport: 1,
status: {
is_live: false
}
},
'2': {
id: 2,
name: 'Competition 2',
short_name: 'Comp 2',
slug: 'comp-2',
sport: 1,
status: {
is_live: true
}
},
'3': {
id: 3,
name: 'National Basketball League',
short_name: 'NBA',
slug: 'national-basketball-league',
sport_slug: 'basketball',
sport: 3,
status: {
is_live: true
}
}
},
allIds: [
'1',
'2',
'3'
]
}
What I want achieve: I want a list of competitions filtered/categorized by sports.
How can I do that?
Also I want to be able to group competitions by it's status.is_live.
So how can I get an list of competitions breakdown by sport that status.is_live equals true and competitions status.is_live equals false?
Any help is appreciated! Thanks
If you don't want to use lodash, you can write a .groupBy function pretty easily (example). You'll need to loop over the output object and reassign its children values with a for instead of using .mapValues.
I used lodash in the example, just to point out the logic.
Note: I'd remove the grouping in the data in the original response, and let the client do this on its own - it's easier to work on an unsorted array and filter/map that instead of working against values from an object that has redundant keys (since they represent groups by Id)
let data = {
sports: {
byId: {
1: {
id: 1,
name: 'Soccer',
slug: 'soccer'
},
2: {
id: 2,
name: 'Basketball',
slug: 'basketball'
},
3: {
id: 3,
name: 'American Football',
slug: 'american-football'
}
},
allIds: [
'1',
'2',
'3'
]
},
competitions: {
byId: {
'1': {
id: 1,
name: 'Competition 1',
short_name: 'Comp 1',
slug: 'comp-1',
sport: 1,
status: {
is_live: false
}
},
'2': {
id: 2,
name: 'Competition 2',
short_name: 'Comp 2',
slug: 'comp-2',
sport: 1,
status: {
is_live: true
}
},
'3': {
id: 3,
name: 'National Basketball League',
short_name: 'NBA',
slug: 'national-basketball-league',
sport_slug: 'basketball',
sport: 3,
status: {
is_live: true
}
}
},
allIds: [
'1',
'2',
'3'
]
}
}
let competitions = Object.values(data.competitions.byId)
// _.chain(arr) keeps returning `lodash` objects
// so I don't have to call it separately for every action
let filteredCompetitions = _.chain(competitions)
.groupBy(i => i.status.is_live)
.mapValues(i => _.groupBy(i, 'sport'))
.value() // returns the final value
console.log(filteredCompetitions)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Categories