mongodb push to embedded array, values of document - mongodb

Hello i have this document
{
name: 'name1',
versions: []
}
and i want to update it to be
{
name: 'name2',
versions: [
{
name: 'name1'
}
]
}
I'm using nodejs and mongoose

try this
doc.findOneAndUpdate(
{ name: "name1"},
{ "$push": { "versions": { name: 'name1' } } }
)

You should use $push. Suppose your using a schema named Person for your example. You should use this:
Person.updateOne(
{ _id: person._id },
{ $push: { versions: {name: 'name1'} } }
)
also if you have already selected the document you want and stored it as person you can use this snippet:
person.versions.push({versions: {name: 'name1'}})

Related

Can populate method in mongoose return a tree structure data

I have a model tree structures with parent references, this is my schema file:
export class Menu {
...
#Prop({ type: Types.ObjectId, ref: 'Menu' })
childrens: Menu[];
}
export const MenuSchema = SchemaFactory.createForClass(Menu);
some data in my database:
[
{
_id: ObjectId('menu1'),
name: 'menu1',
...
childrens: [ObjectId['menu1-1']],
},
{
_id: ObjectId('menu1-1'),
name: 'menu1-1',
...
childrens: [ObjectId['menu1-1-1']],
},
{
_id: ObjectId('menu1-1-1'),
name: 'menu1-1-1',
...
}
]
Now I use populte to query the data.
this.menuModel.findOne({_id:ObjectId('menu1')}).polulate('childrens');
It returns:
{
"_id": "menu1",
"name": "menu1",
...,
"childrens":[
{
"_id": "menu1-1",
"name": "menu1-1",
...
"childrens":["menu-1-1"]
}
]
}
the childrens in menu1-1 is not a Menu model list, just an ObjectId list, so why? The poplute method cannot build a tree structure?If not, how to let query to return a tree? I have try aggregate with $graphLookup method, it seems doesnot work too.

Mongoose append to string while update

I try to append something to a string with findOneAndUpdate
My DB values
{ _id: 'myId', name: 'Name', createdAt: ..... }
I try to append something to my name without doing two queries.
await MongoModel.findOneAndUpdate(
{
_id: 'myId',
},
{
'name': currentString + '_someString',
}
)
and my output should look like
{ _id: 'myId', name: 'Name_someString', createdAt: ..... }
You can try update with aggregation pipeline starting from MongoDB 4.2,
$concat to concat current name and new string
await MongoModel.findOneAndUpdate(
{ _id: "myId" },
[{
$set: {
name: {
$concat: ["$name", "_someString"]
}
}
}]
)
Playground

How to update multiple documents in mongodb using one query from an array of objects

I have the following array of objects...
[
{
_id: 'dfjkldsjfkldjas',
name: 'will'
},
{
_id: 'fdsfdakjdhfaskh',
name: 'bob'
},
{
_id: 'fdsfdasfdfewrfq',
name: 'tom'
}
]
Is there a way to search a mongodb collection for documents that match these _id's and then $set the name in the document all in one query? Maybe using updateMany?
You can use a bulkWrite to achieve this. First map your array and transform the data like so:
const data = [
{
_id: 'dfjkldsjfkldjas',
name: 'will'
},
{
_id: 'fdsfdakjdhfaskh',
name: 'bob'
},
{
_id: 'fdsfdasfdfewrfq',
name: 'tom'
}
]
const bulkData = data.map(item => (
{
updateOne: {
filter: { _id: item._id },
update: { $set: { name: item.name }}
}
})
);
Then you use the method bulkWrite to save the multiple data.
db.yourCollection.bulkWrite(bulkData);
You also don't have to use the same DB operation for every entry, you can use different ones on the same bulk like deleteOne, replaceOne, insertOne, etc.
You can check more here: https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/
Try this for updating bulk data
const data = [
{
_id: 'dfjkldsjfkldjas',
name: 'will'
},
{
_id: 'fdsfdakjdhfaskh',
name: 'bob'
},
{
_id: 'fdsfdasfdfewrfq',
name: 'tom'
}
]
const bulkData = data.map(item => (
{
updateOne: {
filter: { _id: item._id },
update: { $set: { name: item.name } },
upsert: true
}
})
);
await db1.bulkWrite(bulkData, { ordered: false, upsert: true });

Multiple updates queries in MongoDB

couldn't find information about this, hope it's not a repeated question.
I would like to update multiple documents in MongoDB, but using specific queries and update values for each one, for instance, I have this model:
user: {
name: String,
email: String
}
Lets say that I have 2 documents:
User_A: {
name: 'Charles Montoya',
email: 'charles#email.com'
}
User_B: {
name: 'Robbin Faz',
email: 'robbin#email.com'
}
Now, what I would like to do is something like this:
db.user.update([
{ name: 'Robbin Faz' }, { $set: { email: 'robbin#email2.com' }, { upsert: true } },
{ name: 'Charles Montoya' }, { $set: { email: 'charles#email2.com' }, { upsert: true} }
])
If something like this is not possible, which way do you recommend me to work with a list of updates?, or should I do a "for"?
Thank you for your help.
You can do a bulk update and or upset:
> var bulk = db.user.initializeUnorderedBulkOp();
> bulk.find( { name: 'Robbin Faz' } ).upsert().update( { $set: { email: 'robbin#email2.com' } });
> bulk.find( { name: 'Charles Montoya' } ).upsert().update( { $set:{ email: 'charles#email2.com' } });
> bulk.execute();

Using $or (logical query operators) inside $pull (array update operators) does not work in mongoose

Using mongoose to perform the following operation on MongoDB:
model.findOneAndUpdate(
{ name: 'test' },
{
'$set': { name: 'test2' },
'$pull': { some_array: { '$or': [ { name: 2 }, { name: 3 } ] } }
},
function(err, c) { ... }
)
gives the following result seen in mongoose debug logs:
Mongoose: examples.findAndModify(
{ name: 'test' }) [] {
'$pull': { some_array: {} }, '$set': { name: 'test2' }
}
{ upsert: false, new: true }
some_array: {} - is empty, without $or logical operator. This call causes completely removal of some_array array which is an obvious bug.
Such syntax should be supported, because in mongo shell it does work properly using call:
db.examples.findAndModify(
{query:
{ name: 'test' },
update:
{
'$pull': { some_array: { '$or': [ { name: 2 }, { name: 3 } ] } },
'$set': { name: 'test2' }
}}
)
Is it some obvious bug in mongoose driver? If yes, does someone know the corresponding ticket for this issue or it should be reported?
Maybe there is something wrong with mongoose syntax?
Edit:
I've checked also call without $set part:
model.findOneAndUpdate(
{ name: 'test' },
{ '$set': { name: 'test2' },
'$pull': { some_array: { '$or': [ { name: 2, name: 3 } ] } }
},
function(err, c) {...}
);
And it also wrongly matches to:
Mongoose: examples.findOne({ name: 'test' }) { fields: undefined }