$set is overtiring complete array value how to update it
var obj = // contains some other data to update as well
obj.images=images; // updating obj with images []
Units.update({_id: 'id', {$set: obj});
finally my mongo object must be something like this
{
"_id" : "ZhBgrNFtr2LRPkQrZ",
"sitouts" : "test",
"interiors" : "test",
"features" : "test",
"keyHolder" : "test",
"images" : [
"1445481257465-8678-20130520_113154.jpg", ## `updated value ` ##
"1445481257456-3-20130520_113157.jpg",
"1445481258058-5771-20130520_113202.jpg",
"1445481258230-9603-20130521_075648.jpg"
]
}
https://docs.mongodb.org/manual/reference/operator/update/push/
$push, $each, $slice. See the documentation.
Here are a few ways to update the images array without overwriting it:
Update a Specific Index
Units.update({_id: id}, {$set: {'images.0': obj.images[0]}})
Append a Single Value
Units.update({_id: id}, {$push: {images: obj.images[0]}})
Append Multiple Values
Units.update({_id: id}, {$push: {images: {$each: obj.images}}})
Related
I have this collection:
[{ "_id" : 7,
"category" : "Festival",
"comments" : [
{
"_id" : ObjectId("4da4e7d1590295d4eb81c0c7"),
"usr" : "Mila",
"txt" : "This is a comment",
"date" : "4/12/11"
}
]
}]
All I want is to push insert a new field inside comments like this:
[{ "_id" : 7,
"category" : "Festival",
"comments" : [
{
"_id" : ObjectId("4da4e7d1590295d4eb81c0c7"),
"usr" : "Mila",
"txt" : "This is a comment",
"date" : "4/12/11",
"type": "abc" // find the parent doc with id=7 & insert this inside comments
}
]
}]
How can I insert inside the comments subdocument?
You need to use the $ positional operator
For example:
update({
_id: 7,
"comments._id": ObjectId("4da4e7d1590295d4eb81c0c7")
},{
$set: {"comments.$.type": abc}
}, false, true
);
I didn't test it but i hope that it will be helpful for you.
If you want to change the structure of document you need to use
db.collection.update( criteria,
objNew, upsert, multi )
Arguments:
criteria - query which selects the record to update;
objNew - updated object or $ operators (e.g., $inc) which manipulate the object
upsert - if this should be an "upsert"; that is, if the record does not exist, nsert it
multi - if all documents matching criteria should be updated
and insert new objNew with new structure. check this for more details
The $ positional operator is only going to work as expected if the 'comments' field is NOT an array. The OP's json is malformed, but it looks like it could be an array.
The issue is that mongodb right now will only update the first element of an array which matches the query. Though there is an RFE open to add support for updating all matching array elements: https://jira.mongodb.org/browse/SERVER-1243
To work around this issue with arrays you just have to do a regular find then update the elements in the array individually.
I'm trying to $push a value in an array inside mongodb. This is the query:
db.user.update(
{ "_id": 5ac34a3c23f1b0343c155782 },
{ $push: { "courseId":5acd192a3ff62a287452891f}});
The first id, after _id is coming from a user model with this parameter, "_id" : ObjectId("5acb75a9e773ed2c10d5caa8").
The second id, after courseId is coming from this parameter "_id" : ObjectId("5acd192a3ff62a287452891f").
Desired user model should look like:
"_id" : ObjectId("5ac34a3c23f1b0343c155782"),
"tokens" : [ ],
"courseId" : [
"5ac37f5cd494e905b86c2433",
"<new id>"
],
Where am I going wrong?
db.user.update({ "_id": 5ac34a3c23f1b0343c155782 }, { $push: { "courseId":5acd192a3ff62a287452891f}})
You may need to use the "_id": ObjectId("5ac34a3c23f1b0343c155782") instead of just alphanumeric
See if following snippet works for you:
//following query will push to courseId
let modifier = {$push: { "courseId" :"5acd192a3ff62a287452891f"} };
let options = {returnOriginal: false};
db.collection('user').findOneAndUpdate({_id: ObjectId('5ac34a3c23f1b0343c155782')}, modifier, options)
.then(function(op) {
// see success or failure here in op
console.log(op);
})
I'm trying to build a Query that excludes results from an Array when it only contains the String sent in the Query.
I have these two Arrays
Array 1
[ { _id :'first', subCategory : '5K'}, { _id : 'second', subCategory : '10K'}]
Array 2
[ { _id :'first', subCategory : '5K'}]
I want to exclude JUST the second one, so I can't use
query.$and.push({ subCategory: { $nin: '5K }});
I tried this, but it didn't work either :
query.$and.push({ subCategory : { $elemMatch : { $nin : '5K' }}});
Thank you for your time!!
Ok, I solved it.
query.$and.push({ array : { $all : [{ $elemMatch : { subCategory : { $nin : '5K' }}}]}});
I want update an _id field of one document. I know it's not really good practice. But for some technical reason, I need to update it.
If I try to update it I get:
db.clients.update({ _id: ObjectId("123")}, { $set: { _id: ObjectId("456")}})
Performing an update on the path '_id' would modify the immutable field '_id'
And the update is rejected. How I can update it?
You cannot update it. You'll have to save the document using a new _id, and then remove the old document.
// store the document in a variable
doc = db.clients.findOne({_id: ObjectId("4cc45467c55f4d2d2a000002")})
// set a new _id on the document
doc._id = ObjectId("4c8a331bda76c559ef000004")
// insert the document, using the new _id
db.clients.insert(doc)
// remove the document with the old _id
db.clients.remove({_id: ObjectId("4cc45467c55f4d2d2a000002")})
To do it for your whole collection you can also use a loop (based on Niels example):
db.status.find().forEach(function(doc){
doc._id=doc.UserId; db.status_new.insert(doc);
});
db.status_new.renameCollection("status", true);
In this case UserId was the new ID I wanted to use
In case, you want to rename _id in same collection (for instance, if you want to prefix some _ids):
db.someCollection.find().snapshot().forEach(function(doc) {
if (doc._id.indexOf("2019:") != 0) {
print("Processing: " + doc._id);
var oldDocId = doc._id;
doc._id = "2019:" + doc._id;
db.someCollection.insert(doc);
db.someCollection.remove({_id: oldDocId});
}
});
if (doc._id.indexOf("2019:") != 0) {... needed to prevent infinite loop, since forEach picks the inserted docs, even throught .snapshot() method used.
Here I have a solution that avoid multiple requests, for loops and old document removal.
You can easily create a new idea manually using something like:_id:ObjectId()
But knowing Mongo will automatically assign an _id if missing, you can use aggregate to create a $project containing all the fields of your document, but omit the field _id. You can then save it with $out
So if your document is:
{
"_id":ObjectId("5b5ed345cfbce6787588e480"),
"title": "foo",
"description": "bar"
}
Then your query will be:
db.getCollection('myCollection').aggregate([
{$match:
{_id: ObjectId("5b5ed345cfbce6787588e480")}
}
{$project:
{
title: '$title',
description: '$description'
}
},
{$out: 'myCollection'}
])
You can also create a new document from MongoDB compass or using command and set the specific _id value that you want.
As a very small improvement to the above answers i would suggest using
let doc1 = {... doc};
then
db.dyn_user_metricFormulaDefinitions.deleteOne({_id: doc._id});
This way we don't need to create extra variable to hold old _id.
Slightly modified example of #Florent Arlandis above where we insert _id from a different field in a document:
> db.coll.insertOne({ "_id": 1, "item": { "product": { "id": 11 } }, "source": "Good Store" })
{ "acknowledged" : true, "insertedId" : 1 }
> db.coll.aggregate( [ { $set: { _id : "$item.product.id" }}, { $out: "coll" } ]) // inserting _id you want for the current collection
> db.coll.find() // check that _id is changed
{ "_id" : 11, "item" : { "product" : { "id" : 11 } }, "source" : "Good Store" }
Do not use $match filter + $out as in #Florent Arlandis's answer since $out fully remove data in collection before inserting aggregate result, so effectively you will loose all data that don't match to $match filter
Can i Copy Some Field from collection to another collection?
I want copy values of bar to foo collection, but i don't want type filed, and I want insert in foo e new _id e extra field (userId) ( then i use Node.js)
collection bar
{
"_id" : ObjectId("77777777ffffff9999999999"),
"type" : 0,
"name" : "Default",
"index" : 1,
"layout" : "1",
}
collection foo
{
"_id" : NEW OBJECT ID,
// "type" : 0, NO IN THIS COLLECTION
"userId" : ObjectId("77777777ffffff9999999911"),
"name" : "Default",
"index" : 1,
"layout" : "1",
}
I try with db.bar.copyTo("foo"); but copy entire collection
Actually that is probably your best option. But when you don't want the new field in your collection, then just remove it using $unset:
db.foo.update({ },{ "$unset": { "type": 1 } },false,true)
That will remove the field from all documents in your new collection in one statement.
In future releases from 2.6 and upwards you can also do this using aggregate:
db.bar.aggregate([
{ "$project": {
"userId" : 1
"name" : 1
"index" : 1
"layout" : 1
}},
{ "$out": "foo" }
])
The new $out method sends the output of the aggregation statement to a collection.
You can copy fields from one collection to another by using
db.copyFromCollection.find().forEach(function(x){
db.copyToCOllection.update(
{"_id" : ObjectId("53205a4a14952bee39f3376e")}, //some condition for update
{ $set:{parameterOfCopyToCollection:x.parameterOfCopyFromCollection}
});
});
Here we iterate through the data by using the above function.We iterate through the collection from which we want to copy the data and then inside the function we update the document to which we want to add/update that data.