How to update names field nested in an array in mongodb - mongodb

I have this object and I'd like to update the name field "field" of all the document in the collections. I read the mongodb documentation and it says $rename doesn't work in this case. I should execute a forEach but I don't know how which command use
{
"name": "foo"
"array": [
"object": {
"field": "name"
}
]
}

Do it manually:
db.collection.find().forEach(function(doc) {
if (doc.array) {
doc.array.forEach(function(edoc) {
if (edoc.object) {
doc.object.new_field = edoc.object.field
delete edoc.object.field
}
})
db.test.update({ "_id" : doc._id }, doc)
}
})
This should get you started. It handles missing or empty array arrays, but not an array value of the wrong type, or an object value of the wrong type.

$rename modifier for update Ops should work (http://docs.mongodb.org/manual/reference/operator/update/rename/)
Imagine a collection like yours:
{
"name": "foo",
"array":[
{"field": "name" }
]
}
You will be able to do something like this:
db.rename.update({},{$rename:{"name":"newName"}});
And the document will be as follows:
{
"newName": "foo",
"array":[
{"field": "name" }
]
}
In order to update all the collection you should use the multi option as follows:
db.rename.update({},{$rename:{"name":"newName"}}, {multi:true})
Regards

Related

Update a nested field with an unknown index and without affecting other entries

I have a collection with a layout that looks something like this:
student1 = {
"First_Name": "John",
"Last_Name": "Doe",
"Courses": [
{
"Course_Id": 123,
"Course_Name": "Computer Science",
"Has_Chosen_Modules": false
},
{
"Course_Id": 284,
"Course_Name": "Mathematics",
"Has_Chosen_Modules": false
}
]
};
I also have the following update query:
db.Collection_Student.update(
{
$and: [
{First_Name: "John"},
{Last_Name: "Doe"}
]
},
{
$set : { "Courses.0.Has_Chosen_Modules" : true }
}
);
This code will currently update the Computer Science Has_Chosen_Modules value to true since the index is hardcoded. However, what if I wanted to update the value of Has_Chosen_Modules via the Course_Id instead (as the course might not necessarily be at the same index every time)? How would I achieve this without it affecting the other courses that a given student is taking?
You can select any item in the sub array of your document by targeting any property in the sub array of your document by using dot .
You can easily achieve this by the following query.
db.Collection_Student.update(
{
First_Name: "John",
Last_Name: "Doe",
'Courses.Course_Id': 123
},
{
$set : { "Courses.$.Has_Chosen_Modules" : true }
}
);
Conditions in search filter are by default treated as $and operator, so you don't need to specifically write $and for this simple query.

mongodb $ causing error The positional operator did not find the match needed from the query

I’ve been trying to update the data in my mongoDB.
I want to update all products with a new productName field.
my data looks something like:
{
"id": "12345",
"products": [{
"id": 0
"productCode": "test",
"status": "PENDING",
},
{
"id": 1
"productCode": "test",
"status": "COMPLETE",
}],
}
When I try the following. I get this error The positional operator did not find the match needed from the query.
db.customers.updateMany(
{ id: "12345" },
{ $set: {
"products.$.productName": "Name here" }
}
)
If I do account.0.productName then it’s fine and updates. I’m not sure why $ is not working for me
db.customers.updateMany(
{ id: "12345" },
{ $set: {
"products.0.productName": "Name here" }
}
)
Positional operator is not working because you are not using the array into the find (first object)
If you try this query it will work as expected because you have the position finding by products.id.
Otherwise, if you don't have the position into array where update, yo can't use $ operator in this way. You need this query:
db.collection.update({
"id": "12345",
},
{
"$set": {
"products.$[].newField": "test2"
}
},
{
"multi": true
})
Mongo playground example here
Using $[] you can reference the array and add the value into each object.
$[] docs here
It says:
The all positional operator $[] indicates that the update operator should modify all elements in the specified array field.
That's exactly we want :)

how to update partial document of an array

i have a person document, that have list of pets:
{
"personId": "kjadfh97r0",
"pets": [
{
"petId": "dfjkh32476",
"name": "kitty",
"kind": "cat"
},
{
"petId": "askdjfh2794857",
"name": "rexy",
"kind": "dog"
}
]
}
I want to find certain pen inside of certain person and update just some fields, so I did something like:
db.people.findAndModify({
query: { "personId": "kjadfh97r0", "pets.petId": "dfjkh32476" },
update: {"$set":{"pets.$":{"kind":"tiger"}}}
})
but what happens to me is that the whole document is replaced with "kind":"tiger", and I just wanted to update the "kind" field any keep the rest.
You should specify entire path for $set when you update nested document using positional operator, otherwise the document will be replaced:
db.people.findAndModify({
query: { "personId": "kjadfh97r0", "pets.petId": "dfjkh32476" },
update: { $set: {"pets.$.kind": "tiger"} }
})

Update an Element if Position is Unknown with Upsert

It looks like you(/I ) cannot have both upsert and an array element update operation.
If you do (python):
findDct = {
"_id": ObjectId("535e3ab9c36b4417d031402f"),
'events.ids': '176976332'
}
print col.update(findDct, {"$set" : {"events.$.foo": "bar"} }, upsert=True)
It will throw:
pymongo.errors.DuplicateKeyError: insertDocument :: caused by :: 11000 E11000
duplicate key error index: test.col.$_id_ dup key: { : ObjectId('535e3ab9c36b4417d031402f') }
This happens because "_id" is of course an index and mongo tries to insert the document as a new since the find query fails on its 'events.ids': '176976332' part (cheat).
Is it possible to update an unknown element in array with upsert True/how?
Yes it is, but you are going about it in the wrong way. Rather than make "finding" the element that you are not sure whether it exists or not, then try to apply the $addToSet operator instead:
db.collection.update(
{ "_id": ObjectId("535e3ab9c36b4417d031402f" },
{
"$addToSet": { "events": { "foo": "bar" } }
},
{ "upsert": true }
)
Please also note from the positional $ operator documentation that you should not use the $ operator with "upserts" as this will result in the field name being interpreted as a "literal" ( which includes the value as in "events.$.foo" ) and that will be the actual field inserted into the document.
Try to make sure that your array "insert/upsert" operations specify the whole array content in order to make this work.
Another adaptation is with the "bulk" methods, the pymongo driver already has a nice API for this, but this is a general form:
db.runCommand({
"update": "collection",
"updates": [
{
"q": { "_id": ObjectId("535e3ab9c36b4417d031402f" } },
"u": {
"$addToSet": {
"events": {
"foo": "bar", "bar": "baz"
}
}
},
"upsert": true
},
{
"q": { "_id": ObjectId("535e3ab9c36b4417d031402f" } },
"u": {
"$set": { "events.foo": "bar" }
}
}
]
})
But still being very careful that you are not producing duplicates in your sub-document array if you can clearly see the case there. But it is a method, as each update will cascade down even if the first form failed to add anything. Not the best case example, but I hope you see the point.

Nested documents and _id indexes in mongodb

I have a collection with nested documents in it. Each document also has an _id field.
Here's an example of a documents structure
{
"_id": ObjectId("top_level_doc"),
"title": "Cadernos",
"parent": "4fd55bbc5d1709793b000008",
"criterias": {
"0": {
"_id": ObjectId("a_nested_doc"),
"value": "caderno",
"operator": "contains",
"field": "design0"
}
}
}
I want to be able to find the nested document just by searching it's _id
With this query
{
"criterias._id" : ObjectId("a_nested_doc")
}
It returns the parent document (i just want the one that's nested).
Ideally I would do this
{
"_id" : ObjectId("a_nested_doc")
}
And it would return the document with that id (either its nested or not).
Ps. I edited the "_id" values for the sake of simplicity just for this example.
You may have to live with selecting criterias._id (without writing a wrapper around the query, at least), but you can select the document itself by simply retrieving a subset of the fields.
http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields
// The simplest case converted to your use case
db.collection.find( { criterias._id : ObjectId("a_nested_doc") }, { criterias : 1 } );