delete an elemnt from an array inside another array with mongodb - javascript

hello everyone i have a document of materiels where each document has an array of articles and each article has an array of details here's my collection data:
{
"_id": "62f2404b42556d62e2939466",
"code": "120K",
"designation": "PIZZA",
"article": [
{
"etat": "Reçu",
"lot": "",
"marque": "Royal",
"fournisseur": "maatalah",
"dateachat": "2022-08-01T00:00:00.000Z",
"bc": null,
"bl": null,
"fc": null,
"quantite": 12,
"_id": "62f25d001a035d017369e1f8",
"detail": [
{
"serie": "12",
"ddp": "2023-01-01T00:00:00.000Z",
"_id": "62f3986fe462b8a173c7d220"
},
{
"serie": "13",
"ddp": "2023-03-01T00:00:00.000Z",
"_id": "62f39cc1862c1bf5bc40157a"
}
]
},
{
"etat": "Reçu",
"lot": "",
"marque": "margarita",
"fournisseur": "",
"dateachat": "2022-08-04T00:00:00.000Z",
"bc": null,
"bl": null,
"fc": null,
"quantite": 13,
"_id": "62f25d041a035d017369e1fb",
"detail": [
{
"serie": "12345",
"ddp": "2023-01-01T00:00:00.000Z",
"_id": "62f281158a159e976c7c68d5"
}
]
}
],
"qteglobal": 25,
"id": "62f2404b42556d62e2939466"
}
i want to remove an element from the detail array here my express js code:
const { id, idarticle, iddetail } = req.params;
const materiel = Materiel.findOneAndUpdate(
{ _id: id, "article._id": idarticle, "article.detail._id": iddetail },
{ $pull: { "article.$.detail": { _id: iddetail } } },
{ new: true }
);
there is no syntax error but the document it doesn't seem to be deleted.
Can anyone help me please ? thank you

Hello guys after trying some methods i end up with this solution:
const { id, idarticle, iddetail } = req.params;
await Materiel.findOneAndUpdate(
{
id,
"article._id": idarticle,
},
{
$pull: {
"article.$[].detail": {
_id: iddetail,
},
},
}
);

Related

How to update nested object in array (Mongoose/MongoDB)

I've been struggling to get my around how to update a object in a nested array with a particular id. I've attempted to implement $set as shown below. I want to be able to update the task with an _id of 62ff74bfe80b11ade2d34455 with the data from the request body.
{
"_id": "62fa5aa25778ec97bc6ee231",
"user": "62f0eb5ebebd0f236abcaf9d",
"name": "Marketing Plan",
"columns": [
{
"name": "todo",
"_id": "62fa5aa25778ec97bc6ee233",
"tasks": [
{ ====> here
"title": "Task Four",
"description": "This is task four",
"subtasks": [
{
"name": "wash dshes",
"completed": false,
"_id": "62ff74bfe80b11ade2d34456"
},
{
"name": "do homework",
"completed": false,
"_id": "62ff74bfe80b11ade2d34457"
}
],
"_id": "62ff74bfe80b11ade2d34455"
}
]
},
{
"name": "doing",
"_id": "62fa5aa25778ec97bc6ee234",
"tasks": []
},
{
"name": "done",
"_id": "62fa5aa25778ec97bc6ee235",
"tasks": []
}
],
"__v": 0
}
const updatedTask = await Board.findOneAndUpdate(
{
"columns.tasks._id": req.params.id,
},
{ $set: { "columns.$.tasks": req.body } },
{ new: true }
);
You can use the positional operator in combination with an arrayfilter. Here's an example how you'd update a specific field of the relevant task:
db.collection.update({
"columns.tasks._id": req.params.id
},
{
"$set": {
"columns.$[].tasks.$[t].title": "it works"
}
},
{
"arrayFilters": [
{
"t._id": req.params.id
}
]
})
You can also try this on mongoplayground.
If you're looking for a way to replace the matching task object itself you can do:
db.collection.update({
"columns.tasks._id": req.params.id
},
{
"$set": {
"columns.$[].tasks.$[t]": req.body
}
},
{
"arrayFilters": [
{
"t._id": req.params.id
}
]
})

Get field of JSON in Javascript Console

I have a JSON like this, how to get the value of StatusDescription? I tried many times but the result is undefined. Here is my JSON:
{
"meta": {
"a2": 200,
"ta": "dasd",
"asdd": "asdda"
},
"data": {
"items": [
{
"id": "",
"number": "",
"origin_info": {
"ItemReceived": "2021-10-02 02:07:49",
"phone": 123456789,
"trackinfo": [
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
},
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
}
]
},
"destination_info": null,
"lastEvent": "grgrgrgrgr",
"lastUpdateTime": "mewmemew"
}
]
}
}
I'm using in my NodeJS app, like myapp.js, and console.log()
Try this
I stored your sample json in variable json
var json = {
"meta": {
"a2": 200,
"ta": "dasd",
"asdd": "asdda"
},
"data": {
"items": [
{
"id": "",
"number": "",
"origin_info": {
"ItemReceived": "2021-10-02 02:07:49",
"phone": 123456789,
"trackinfo": [
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
},
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
}
]
},
"destination_info": null,
"lastEvent": "grgrgrgrgr",
"lastUpdateTime": "mewmemew"
}
]
}
}
Accessed it like below
console.log(json.data.items[0].origin_info.trackinfo[0].StatusDescription);
Items is an array and we took array element 0.
trackinfo again is an array and we took array element 0.
We can change array index or loop through and get required values.
You have to iterate through your items and trackinfo to get to StatusDescription. Try this one.
const data = {
"meta": {
"a2": 200,
"ta": "dasd",
"asdd": "asdda"
},
"data": {
"items": [
{
"id": "",
"number": "",
"origin_info": {
"ItemReceived": "2021-10-02 02:07:49",
"phone": 123456789,
"trackinfo": [
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
},
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
}
]
},
"destination_info": null,
"lastEvent": "grgrgrgrgr",
"lastUpdateTime": "mewmemew"
}
]
}
}
const items = data.data.items.map(item => item)
const trackinfo = items.map(item => item.origin_info.trackinfo).flat()
console.log(trackinfo)
const statusDescription = trackinfo.map(trackinfo => trackinfo.StatusDescription)
console.log(statusDescription)

Add JSON to empty array issue

I have a top level JSON structure as follows:
{
"video": [],
"messages": [],
"notifications": []
}
and i have a database output (in variable "result") as follows i want to push into the "video" array:
[
{
"_id": "5f98ab906439155cfc6f9afb",
"status": "NOT_STARTED",
"date": "2020-10-27T23:21:52.683Z",
"callInvitees": [
{
"username": "user1"
},
{
"username": "user2"
}
]
},
{
"_id": "5f98aba0789e163e0c78908f",
"status": "NOT_STARTED",
"date": "2020-10-27T23:22:08.048Z",
"callInvitees": [
{
"username": "user1"
}
]
}
]
My code is:
let dashboardJSON = { "video": [], "messages": [], "notifications": [] };
dashboardJSON.video.push(result)
It works but i am ending up with too many arrays (i think) - it looks as follows:
{
"video": [
[
{
"_id": "5f98ab906439155cfc6f9afb",
"status": "NOT_STARTED",
"date": "2020-10-27T23:21:52.683Z",
"callInvitees": [
{
"username": "user1"
},
{
"username": "user2"
}
]
},
{
"_id": "5f98aba0789e163e0c78908f",
"status": "NOT_STARTED",
"date": "2020-10-27T23:22:08.048Z",
"callInvitees": [
{
"username": "user1"
}
]
}
]
],
"messages": [],
"notifications": []
}
I want "video": [ { ... }, { ... } ] whereas i have "video": [[ { ... }, { ... } ]]
How can i resolve this?
You can use the spread operator as follows:
let result = [
{
"_id": "5f98ab906439155cfc6f9afb",
"status": "NOT_STARTED",
"date": "2020-10-27T23:21:52.683Z",
"callInvitees": [
{
"username": "user1"
},
{
"username": "user2"
}
]
},
{
"_id": "5f98aba0789e163e0c78908f",
"status": "NOT_STARTED",
"date": "2020-10-27T23:22:08.048Z",
"callInvitees": [
{
"username": "user1"
}
]
}
]
let dashboardJSON = { "video": [], "messages": [], "notifications": [] };
dashboardJSON.video.push(...result)
console.log(dashboardJSON);
Just use Array.prototype.map() method. Map method returns a new array with the result by using the provided function.
const ret = {
video: [],
messages: [],
notifications: [],
};
const data = [
{
_id: '5f98ab906439155cfc6f9afb',
status: 'NOT_STARTED',
date: '2020-10-27T23:21:52.683Z',
callInvitees: [
{
username: 'user1',
},
{
username: 'user2',
},
],
},
{
_id: '5f98aba0789e163e0c78908f',
status: 'NOT_STARTED',
date: '2020-10-27T23:22:08.048Z',
callInvitees: [
{
username: 'user1',
},
],
},
];
ret.video = data.map((x) => x);
console.log(ret);

Adding property to mulitple documents in mongoDB

I have this data structure:
{
"_id": "5ebd08794bcc8d2fd893f4a7",
"username": "johan#gmail.com",
"password": "123",
"decks": [{
"cards": [{
"_id": "5ebd08794bcc8d2fd893f4a9",
"planeetnaam": "Venus",
"kleur": "Grijs"
},
{
"_id": "5ebd08794bcc8d2fd893f4aa",
"planeetnaam": "Neptunus",
"kleur": "Paars"
}
],
"_id": "5ebd08794bcc8d2fd893f4a8",
"name": "Planeten"
},
{
"cards": [{
"_id": "5ebd08794bcc8d2fd893f4ac",
"diernaam": "Hond",
"poten": "4"
},
{
"_id": "5ebd08794bcc8d2fd893f4ad",
"diernaam": "Kangoeroe",
"poten": "2"
}
],
"_id": "5ebd08794bcc8d2fd893f4ab",
"name": "Dieren"
}
],
"__v": 0
}
Now i want to add a new property to all the cards in deck with deckname: "Planeten". How do i do this with a mongoose query?
The cards array of deck "Planeten" should look like this after the query
"cards": [{
"_id": "5ebd08794bcc8d2fd893f4a9",
"planeetnaam": "Venus",
"kleur": "Grijs",
"newProp": null
},
{
"_id": "5ebd08794bcc8d2fd893f4aa",
"planeetnaam": "Neptunus",
"kleur": "Paars",
"newProp": null
}
],
EDIT:
This works in Robo3T:
db.getCollection('users').findOneAndUpdate(
{ '_id': ObjectId("5eba9ee0abfaf237f81fb104") },
{ $set: { 'decks.$[deck].cards.$[].newProp': null } },
{ arrayFilters: [{ 'deck._id': ObjectId("5eba9ee0abfaf237f81fb108") } ] }
)
But the server query doesnt edit any data:
User.findOneAndUpdate(
{ '_id': req.session.userid },
{ $set: { 'decks.$[deck].cards.$[].newProp': null } },
{ arrayFilters: [{ 'deck._id': req.params.deckid } ] }, function(err, user){
res.send('test');
})
Thanks in advance
you can use array update operators
the query may look something like that
db.collection.updateOne(
{ _id: <ObjectId> }, // the filter part
{ $set: { 'decks.$[deck].cards.$[].newProp': null } },
{ arrayFilters: [{ 'deck.name': 'Planeten' }] }
)
$[deck] refers to each element in the decks array
$[] is used to update all the elements in the cards array
your function may look something like that
User.updateOne(
{ '_id': req.session.userid },
{ $set: { 'decks.$[deck].cards.$[].newProp': null } },
{ arrayFilters: [{ 'deck.name': 'Planeten' }] })
.then(function (user) {
if (!user) {
res.status(404).send('Er ging helaas iets fout')
} else {
res.status(201).send("Card is toegevoegd");
}
})
hope it helps

Build tree from flat array using two data tables in Javascript

I'm stuck with creating tree structure from a flat array using two Mock data tables in JSON.
the table should match the two unique id to determine the hierarchy between them.
JSON with Groups DB array looks like that:
{
"group": [
{
"groupName": "ROOT",
"id": 1
},
{
"groupName": "Family",
"id": 9
},
{
"groupName": "BestFriends!",
"id": 10
},
{
"groupName": "Cars",
"id": 4
},
{
"groupName": "funHouse",
"id": 3
}
]
};
JSON including Users array looks like that:
{
"user": [
{
"username": "StrongGoose",
"password": "sdff12fdsa",
"age": 31,
"id": 2
},
{
"username": "John",
"password": "sdjd34fffdsa",
"age": 31,
"id": 3
},
{
"username": "Mary",
"password": "sdfffdsa",
"age": 31,
"id": 4
}
]
};
this is how is the first data table looks like and determines the hierarchy between groups:
{
"GroupsToGroups": [
{
"1":[9,10]
},
{
"10":[3]
}
]
};
The second looks like that and determines which user belongs to which group:
{
"GroupsToUsers": [
{
"11":[2]
},
{
"3":[3]
},
{
"4":[4]
},
{
"10":[2]
},
{
"3":[3]
}
]
};
The Hierarchy should look like that, needs to be written to JSON
[
{
"type": "group",
"id": "1",
"name": "ROOT",
"items": [
{
"type": "group",
"id": "9",
"name": "Family",
"items": []
},
{
"type": "group",
"id": "10",
"name": "BestFriends!",
"items": [
{
"username": "StrongGoose",
"password": "sdff12fdsa",
"age": 31,
"id": 2
},
{
"type": "group",
"id": "3",
"name": "funHouse",
"items": [
{
"username": "John",
"password": "sdjd34fffdsa",
"age": 31,
"id": 3
},
{
"type": "group",
"id": "4",
"name": "Cars",
"items": [
{
"username": "Mary",
"password": "sdfffdsa",
"age": 31,
"id": 4
}
],
}
]
}
]
}
]
}
];
edit: i have tried to create a function with a recursion that finds the relevant related groups.
it works but i don't know how to combine the users.
function checkChildren(group) {
const allChildren = insideGroups[group.id];
if (!allChildren) return group;
const childGroups = allChildren.map((findChildrenID) => {
const indexGroups = groups.findIndex((subGroup) => subGroup.id ===
findChildrenID);
return checkChildren(groups[indexGroups]);
});
return Object.assign({}, group, {groups: childGroups});
}
You could take a hash table for the various types of data for a faster accesss without iterating the arrays of objects.
In the case of users, you need anyway a new object with new properties and renamed keys.
Then you need a new property for the root objects and add it to the groups.groups property to have the same access type for all levels.
Ath the end iterate first groups.users and then groups.groups to get all object and for the groups, take the children as well.
In the given data I commented the unused/duplicate data.
function getNodes(node) {
return [
...(hash.groups.users[node] || []).map(id => hash.user[id]),
...(hash.groups.groups[node] || []).map(id => Object.assign(hash.group[id], { children: getNodes(id) }))
];
}
var db = {
group: [
{ groupName: "ROOT", id: 1 },
{ groupName: "Family", id: 9 },
{ groupName: "BestFriends!", id: 10 },
{ groupName: "Cars", id: 4 },
{ groupName: "funHouse", id: 3 }
],
user: [
{ username: "StrongGoose", password: "sdff12fdsa", age: 31, id: 2 },
{ username: "John", password: "sdjd34fffdsa", age: 31, id: 3 },
{ username: "Mary", password: "sdfffdsa", age: 31, id: 4 }
],
GroupsToGroups: [
{ 1: [9, 10] }, // ok
{ 10: [3] }, // second
{ 3: [4] }
],
GroupsToUsers: [
//{ 11: [2] }, // never used
{ 3: [3] },
{ 4: [4] },
{ 10: [2] }, // first
//{ 3: [3] } // dupe
]
},
hash = {
group: Object.assign(...db.group.map(({ id, groupName: name, type = 'group' }) => ({ [id]: { type, id, name } }))),
user: Object.assign(...db.user.map(o => ({ [o.id]: o }))),
groups: {
groups: Object.assign(...db.GroupsToGroups, { root: db.group.filter(({ groupName }) => groupName === 'ROOT').map(({ id }) => id) }),
users: Object.assign(...db.GroupsToUsers)
}
},
result = getNodes('root');
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories