Update an item in an array that is in an array - mongodb

I have a document in a mongodb collection like this :
{
sessions : [
{
issues : [
{
id : "6e184c73-2926-46e9-a6fd-357b55986a28",
text : "some text"
},
{
id : "588f4547-3169-4c39-ab94-8c77a02a1774",
text : "other text"
}
]
}
]
}
And I want to update the issue with the id 588f4547-3169-4c39-ab94-8c77a02a1774 in the first session.
The problem is that I only know that it's the first session and the issue id (NOT the index of the issue !)
So I try something like this :
db.mycollection.update({ "sessions.0.issues.id" : "588f4547-3169-4c39-ab94-8c77a02a1774"},
{ $set: { "sessions.0.issues.$.text" : "a new text" }})
But I got the following result :
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16837,
"errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: sessions.0.issues.$.text"
}
How can I do this ?
Thanks for help.

You have to use this (apparently equivalent) query:
db.mycollection.update({"sessions.0.issues": {$elemMatch: {id: <yourValue>}}}, {$set: {"sessions.0.issues.$.text": "newText"}})
Notice that your update expression was correct.
More information about $elemMatch.
Btw, MongoDB reference explicits that $ operator does not work "with queries that traverse nested arrays".
Important: $elemMatch only works with version 4 or more.

Related

How to update hours in data field in mongodb

I have set of mongo document, I need to convert/update the below values like ("workedDate" : ISODate("2020-07-01T00:00:00Z"))
"workedDate" : ISODate("2020-07-01T20:03:04Z"),
"workedDate" : ISODate("2020-07-01T19:59:07Z"),
"workedDate" : ISODate("2020-06-30T14:00:00Z"),
"workedDate" : ISODate("2020-07-01T19:49:29Z")
I have tried the below query:
db.timeentrys.update(
{ },
{
$set: {
workedDate:{$dateFromParts:{
year:{$year:"$workedDate"},
month:{$month:"$workedDate"},
day:{$dayOfMonth:"$workedDate"}
}}
}
}
)
Getting the below error :
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 52,
"errmsg" : "The dollar ($) prefixed field '$dateFromParts' in 'workedDate.$dateFromParts' is not valid for storage."
}
})
$dateFromParts is an aggregation expression. You can only use aggregation expressions in an update if you are using MongoDB 4.2, and provide a pipeline array as the second argument to update instead of an object.
Edit
In this use, just wrap the update object in [] to make it an array:
db.timeentrys.update(
{ },
[{$set: {
workedDate:{$dateFromParts:{
year:{$year:"$workedDate"},
month:{$month:"$workedDate"},
day:{$dayOfMonth:"$workedDate"}
}}
}}]
)

db.collections.updateOne(filter,update,options) not working with $pull operator

I am just running a db.collections.updateOne() query on mongo shell with $pull operator. It works as expected with $set operator but doesn't affect the document with $pull. Am I missing something here?
Thanks
I found an answer to the same problem someone else posted here How to remove embedded scheme document in mongoose?
I dont seem to see where I am going wrong with this
db.vendors.findOne({"_id":ObjectId("5da0343c724f9d0531eeaa4a")})
This is the document I need to update:
{
"_id" : ObjectId("5da0343c724f9d0531eeaa4a"),
"elements" : [
ObjectId("5da03451724f9d0531eeaa4b")
],
"packages" : [ ],
"title" : "test again",
"slug" : "celebration-company",
"__v" : 1,
"department" : ObjectId("5d9892b1c46b6306b2ce64aa")
}
Here is what I am running on the shell:
db.vendors.updateOne({"_id":ObjectId("5da0343c724f9d0531eeaa4a")},
{$pull:
{"elements":
{"_id":ObjectId("5da03451724f9d0531eeaa4b")}
}
})
Result:
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }

mongodb getting on simple $push The positional operator did not find the match needed from the query

I have this simple update api invocation :
this is my document :
{
"_id" : ObjectId("577a5b9a89xxx32a1"),
"oid" : {
"a" : 0,
"b" : 0,
"c" : NumberLong("1260351143035")
},
"sessions" : [
{
}
]
}
Then i try to insert 1 element into sessions array :
db.getCollection('CustomerInfo').update({"oid.c":1260351143035},{$push:{"sessions.$.asessionID":"test123"}})
but im getting this error:
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16837,
"errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: sessions.$.asessionID"
}
})
using $set im getting the same error
As the error implies,
"The positional operator did not find the match needed from the query.
Unexpanded update: sessions.$.asessionID",
the positional operator will work if the array to be updated is also part of the query. In your case, the query only involves the embedded document oid. The best update operator to use in your case is the $set instead.
You can include the sessions array in the query, for example:
db.getCollection('CustomerInfo').update(
{
"oid.c": 1260351143035,
"sessions.0": {} // query where sessions array first element is an empty document
/* "sessions.0": { "$exists": true } // query where sessions array first element exists */
},
{
"$set": { "sessions.$.asessionID": "test123" }
}
)
As the documentation says, you can do as the follow:
db.getCollection('CustomerInfo').update(
{ "oid.c": 1260351143035 },
{ $push: {
"sessions": {
"asessionID":"test123"
}
}
}
)

MongoDB: updating the value of an inner BSON

I have a document with a schema in mongodb that looks like this:
{
"_id" : ObjectId("572f88424de8c74a69d4558c"),
"storecode" : "ABC",
"credit" : true,
"group" : [
{
"group_name" : "Frequent_Buyer",
"time" : NumberLong("1462732865712"),
}
],
}
I want to add on the _id part for the first object in the array under group so it looks like this:
{
"_id" : ObjectId("572f88424de8c74a69d4558c"),
"storecode" : "ABC",
"credit" : true,
"group" : [
{
"group_name" : "Frequent_Buyer",
"time" : NumberLong("1462732865712"),
"_id" : "573216fee4430577cf35e885"
}
],
}
When I try this code it fails:
db.customer.update({ "_id": ObjectId("572f88424de8c74a69d4558c") },{ "$set": { "group.$._id": "573216fee4430577cf35e885"} })
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16837,
"errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: groups.$._id"
}
})
However, if I adjust the code slightly and add on an extra criteria for querying, it works:
db.customer.update({ "_id": ObjectId("572f88424de8c74a69d4558c"), "group.groupname": "Frequent_Buyer" },{ "$set": { "group.$._id": "573216fee4430577cf35e885"} })
Results:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Why did the first command not work but the second command work?
This is the expected result. To use the positional $ update operator, the array field must appear as part of the query document as mentioned in the documentation.
When used with update operations, e.g. db.collection.update() and db.collection.findAndModify(),
the positional $ operator acts as a placeholder for the first element that matches the query document, and
the array field must appear as part of the query document.
For example If you don't want to filter your documents using group_name, simply add group: { "$exists": true } or "group.0": { "$exists": true } to your query criteria. You query will then look like this:
db.customer.updateOne(
{
"_id": ObjectId("572f88424de8c74a69d4558c"),
"group.0": { "$exists": true}
},
{ "$set": { "group.$._id": "573216fee4430577cf35e885" } }
)
Last and not least, you should be using updateOne or updateMany because update is deprecated in official language driver.

Yet another MongoDB findAndModify

Please consider the following document, a part of the Runtime collection:
{
"entity_id" : 10,
"features" : [
{
"10" : "Test System 2"
},
{
"20" : "System 2 Description"
},
{
"180" : ISODate("2013-12-25T18:19:40.589Z")
},
{
"190" : ISODate("2013-12-25T18:19:40.589Z")
}
],
"_id" : ObjectId("52bb21bc8a2ebdc01c000001")
}
My goal is to update the value of the element of the "features" array having the key "20".
Here are the things I've tried (in mongo shell):
db.Runtime.findAndModify({ "query" : {"_id": "52bb21bc8a2ebdc01c000001"}, "update" : {$set : {"features.$.20":"Updated Description"}}} );
db.Runtime.findAndModify({ "query" : {"_id": "52bb21bc8a2ebdc01c000001"}, "update" : {$set : {"features['20']":"Updated Description"}}} );
db.Runtime.findAndModify({ "query" : {"_id": "52bb21bc8a2ebdc01c000001"}, "update" : {$set : {"features[1]":"Updated Description"}}} );
In all instances the shell prints
null
and nothing happens to the data. So, the main question is, of course, what is wrong with my code snippets. Also, how that "null" is supposed to get interpreted? And is there such a thing as mongo shell's log where one could find any clues? Many thanks for your help!
When using the $ positional operator in an update, your query needs to include a term that matches the element of the array you're updating:
db.Runtime.findAndModify({
query: {_id: ObjectId("52bb21bc8a2ebdc01c000001"),
'features.20': {$exists: true}},
update: {$set: {"features.$.20":"Updated Description"}}
})
Note that you also need to call ObjectId on your _id string to turn it into an actual ObjectId or it won't match the doc.