Mongoose add/remove items from nested array - node.js

I have a document that has a nested array that I need to add/remove items from. Normally you query a nested object by id but in this case a dynamic object _id wont work and I need to update by the nested profile id.
Document
{
title: 'Title',
members: [
{
profile: { id: '123', name: 'Foo' },
items: ['id1', 'id2', 'id3']
}
]
}
Query
My thinking is I need some sort of $elemMatch & $pushAll combo but cant seem to get it working. For removing items from the array I would swap push for pull
await this.repo.findByIdAndUpdate(id, {
members: {
$elemMatch: { 'profile.id': '123' },
$pushAll: {
items: ['xxx', 'yyy'],
},
},
})

You need to use arrayFilters & $push with $each since $pushAll has been deprecated
db.collection.update({},
{
$push: {
"members.$[x].items": {
$each: [
"xxx",
"yyy"
]
}
}
},
{
arrayFilters: [
{
"x.profile.id": "123"
}
]
})
playground

Related

Find just one subdocument of query (two nested arrays) with mongoose

I'm trying to extract just the right element of an array nested in an array inside a mongoDB document.
This is my example document:
[
{
"name": "name1",
"list1": [
{
"name2": "elem1",
"list2": [
{
"name3": "elem 11"
},
{
"name3": "elem22"
}
]
}
],
{...}
}
]
I want to take just the element of the array with name=name1, name2=eleme1 and name3=elem22.
I want to avoid to use "aggregate", but the idea is the use of findOne().
I tried the following query
this.findOne({ name: "name1", list1: { $elemMatch: { name2: "elem1"}}, 'list1.list2': { $elemMatch: { name3: "elem22"} }})
.select({ list1: { $elemMatch: { name1: "elem1" }})
.select({ "list1.list2": { $elemMatch: { name2: "elem22" }}).
There is an error in the syntax, but If I remove the second select, it selects just an element of the array "list1".
Thanks for your help

Node.js- Add new field in array of Mongodb object

I have a collection of users that has an array of multiple plates :
users : [
{
_id: '61234XXX'
plates: [
{
_id: '123'
'color': 'orange'
},
{
_id: '124'
'color': 'blue'
}
]
},
{
_id: '63456XXX'
plates: [
{
_id: '321'
'color': 'orange'
},
{
_id: '432'
'color': 'green'
}
]
}
]
I'm trying to figure out a way to add a new field to the all current plate objects for every user:
I've got to this:
await User.findOneAndUpdate(
{ _id: '63456XXX' },
{
$set : {
[`plates.0.plateStyle`]: "testValue"
}
}
)
Tho this works it's not fit for purpose. Is there a better way I can iterate over this?
You can try this query:
Here you are using array filters to tell mongo: "Where you find an object with _id: "61234XXX" and exists the plates then, there, get the document (elem) which match that plates is not empty (to get all) and add plateStyle".
await User.updateMany({
_id: "61234XXX",
plates: {
$exists: true
}
},
{
$set: {
"plates.$[elem].plateStyle": "testValue"
}
},
{
arrayFilters: [
{
elem: { $ne: [ "$plates", [] ] }
}
]
})
Example here
Also if you are finding by _id you won't need updateMany since _id is unique and only will be 1 or 0 results.

MongoDB: pullAll / pull whole nested array object by value using mongoose

I want to pull the whole nested array object if the object contains a specified string for a specific key. I'm using mongoose with nodejs:
DB before deletion:
{ _id : 1234
fallBackData: {
nestedKey: [ { arrayKey: "theValue" }, { arrayKey: "anotherValue" } ]
}
}
DB after deletion:
{ _id : 1234
fallBackData: {
nestedKey: [ { arrayKey: "anotherValue" } ]
}
}
I took a look at How can I pull nested object value in mongodb and $pullAll Mongo DB docs ,tried the following, but none worked:
const ad = await Ad.updateOne(
{ _id: 1234 },
{
$pullAll: {
fallbackData: { nestedKey: [{ arrayKey: "theValue"}] },
},
}
);
const ad = await Ad.updateOne(
{ _id: 1234 },
{
$pullAll: {
"fallbackData.$.nestedKey" : { arrayKey: "theValue" },
},
}
);
const ad = await Ad.updateOne(
{ _id: 1234 },
{
$pullAll: {
"fallbackData.$.nestedKey" : [{ arrayKey: "theValue"}],
},
}
);
The query return value is the following, but the object in the array is not deleted:
{
acknowledged: true,
modifiedCount: 1,
upsertedId: null,
upsertedCount: 0,
matchedCount: 1
}
You can achieve this by changing a little
playground
db.collection.update({
_id: 1234,
"fallBackData.nestedKey": {
$elemMatch: {
"arrayKey": "theValue"
}
}
},
{
"$unset": {
"fallBackData": "nestedKey"
}
})
You cannot add matching conditions with $pullAll related to Array
$pullAll expects an array of matching values to be removed
You can do $pull instead of $unset but $pull results empty array
The answer from #Gibbs removes the array completely, while you asked only to pull the specific object from it.
Here is the simple solution with $pull command:
db.collection.update({
_id: 1234,
"fallBackData.nestedKey": {
$elemMatch: {
"arrayKey": "theValue"
}
}
},
{
$pull: {
"fallBackData.nestedKey": {
arrayKey: "theValue"
}
}
})
Mongo Playground link
pullAll matches the entire object (or objects) to be pulled. In other words, if the input was:
[
{
_id: 1234,
fallBackData: {
nestedKey: [
{
arrayKey: "theValue",
foo: "bar"
},
{
arrayKey: "anotherValue",
foo: "baz"
}
]
}
}
]
Then you need to do:
db.collection.update({
_id: 1234
},
{
$pullAll: {
"fallBackData.nestedKey": [
{
arrayKey: "theValue",
foo: "bar"
}
]
}
})
See https://mongoplayground.net/p/iJkfqIWK0JO.
On the other hand, $pull can match objects based on a condition, so you can pull from the array based on the specific key you want to match. So, given the same input as above, you would simply do:
db.collection.update({
_id: 1234
},
{
$pull: {
"fallBackData.nestedKey": {
arrayKey: "theValue"
}
}
})
See https://mongoplayground.net/p/MOuSmh7Ir7b.
The conditions can be more complex than a simple field value match. For example to match and pull multiple keys:
db.collection.update({
_id: 1234
},
{
$pull: {
"fallBackData.nestedKey": {
"arrayKey": {
$in: [
"theValue",
"anotherValue"
]
}
}
}
})
See https://mongoplayground.net/p/iSMVxp7a9TX.

Pull element from an array of arrays MongoDb

I am struggling to find the format for a query to remove an element (with an _id) from an array of arrays in Mongo.
When looking at the docs I couldn't find anything that was similar to what I have
https://www.mongodb.com/docs/manual/reference/operator/update/pull/#up._S_pull
I know: the _id of the document in MySchema and the _id of the array element in innerArray.
I don't know the outerArray _id
Could someone help point out where I went wrong Thank you!
This is an example of the data (imagine the _id in ObjectId)
{
outerArray:[
{
_id: 1
innerArray: [{_id: 23, name: '123'}, {_id: 13, name: 'asdac'} ]
},
{
_id: 2,
innerArray: [{_id: 16,name:'asf' }, {_id: 18,name:'asf' } ]
},
{
_id: 3,
innerArray: [{_id: 136,name:'asf' }, {_id: 128,name:'asf' } ]
}
]
}
innerIds is an array of mongoose.Types.ObjectId
return MySchema.updateOne(
{
_id: documentId,
},
{ $pull: { outerArray: { innerArray: { _id: { $in: innerIds } } } } },
)
.session(session)
.exec()
db.collection.update({},
{
$pull: {
"outerArray.$[].innerArray": {//$[] does the trick
_id: {
$in: [
16
]
}
}
}
})
playground

Mongoose, Add/Update data to a set of documents of a collection

Hello guys here's the situation of my problem:
My Categories model looks like this:
schema: {
_id: String,
name: String,
overview: String,
courses: [
{
_id: String,
name: String
}
]
}
I have multiple categories recorded, in the above collection Categories
WHAT I NEED
I have an [ array ] of Categories._id like this:
[
'5812f3cb04700f2563c0e56a',
'5812f3ff04700f2563c0e56b',
...
]
All I want is to PUSH this object {_id:5812f3ff04700f2563c0e56b, name:'SOMETHING' } to all the documents listed in the array of _id
WHAT I TRIED
Categories.update({
'_id': {
$in : array_of_IDs
}
},
{
$push :{
'courses':{ _id: ret._id , name: ret.title }
}
}, function(err, respp){
if(err) return res.negotiate(err);
else{
req.addFlash('success', 'Categories updated successfully.');
return res.redirect('/new-course');
}
}
);
This above code is updating only one collection (the collection with 1st ID in the array of IDs)
Please help!
Thanks
can try using multi: true as option
Categories.update({
'_id': {
$in : array_of_IDs
}
},
{
$push :{
'courses':{ _id: ret._id , name: ret.title }
}
},{ multi: true }, function(err, respp){
//....
}
);

Resources