Update Query in MongoDB with where conditions - mongodb

{
"_id" : ObjectId("510902fb7995fe3504000002"),
"name" : "Gym",
"status" : "1",
"whichs" : [
{
"name" : "American",
"status" : "1"
}
]
}
Above is my collection object.. I want to update which.name to "Indian" where which.status = 1.. Please help me with the mongoDB query for doing this..

You can try this:
db.collection.update({"whichs.status" : "1" },
{$set : { "whichs.$.name" : "Indian"},
false,
true);
This finds "whichs.status" : "1" then sets "whichs.$.name" : "Indian" for all documents. For more info on the update() method, read here.

Starting from MongoDB v3.6, you can use arrayFilters, to perform array update operation.
db.collection.update({
"whichs.status": "1"
},
{
$set: {
"whichs.$[element].name": "Indian"
}
},
{
arrayFilters: [
{
"element.status": "1"
}
]
})
Mongo Playground

Related

Update inner array in multiple array document

I am trying this question... I don't want use the "_id" : "12", field..
{
"_id" : ObjectId("62622dd73905f04f59db2971"),
"array1" : [
{
"_id" : "12",
"array2" : [
{
"_id" : "123",
"answeredBy" : []
},
{
"_id" : "124",
"answeredBy" : []
}
]
}
]
}
I am trying to update using the following query
db.getCollection('nestedArray').updateMany(
{'array1.array2._id':'123'},
{$push:{'array1.array2.$[inner].answeredBy':'success'}},
{arrayFilters:[{'inner._id':'123'}]}
)
But I am getting the following error:
"errmsg" : "The path 'array1.array2' must exist in the document in
order to apply array updates.",
I just trying to understand what is wrong with the code....
add $[] between array1 and array2
Update Nested Arrays in Conjunction with $[]
db.collection.update({
"array1.array2._id": "123"
},
{
$push: {
"array1.$[].array2.$[inner].answeredBy": "success"
}
},
{
arrayFilters: [
{
"inner._id": "123"
}
]
})
mongoplayground

Mongodb $nin not working with nested array

I can't make $nin work with nested arrays, can you guys spot any issue with this query?
I'm basically trying to update the status of every document under items to "closed" in case their hash field is not in a list of hashes provided.
db.getCollection('projects').update({
name: 'test',
'issues.hash': { $nin: [
'8ff28fcc9cbf10c9b690bb331e5609efbd3c526be4f536ebca02cc51bd63eac7',
'd5368ad5658ec11103796255d127d26da7f3324cdedbd124bdd5db50812d588e',
'37298229097785ebc9d419cc1a3f13e0d090a15ceb9a8e6bea3505366902556d',
'fad290f2ddd0e097e4098c3b2c3d65611406cf208a3f86924d45c7736393b44b'
]}
},
{
$set: { "issues.$.status": "closed" }
}
)
This is the data:
{
"_id" : ObjectId("611bb4d2ee06769a5f6d906d"),
"name" : "test",
"issues" : [
{
"_id" : ObjectId("611bb4d20b2fb200167aa588"),
"status" : "open",
"hash" : "8ff28fcc9cbf10c9b690bb331e5609efbd3c526be4f536ebca02cc51bd63eac7"
},
{
"_id" : ObjectId("611bb4d20b2fb200167aa589"),
"status" : "open",
"hash" : "3b83e469049e46b16d3471a188d3f5e3ddbf6b296995a71765bbf17b7289e6ea"
},
{
"_id" : ObjectId("611bb4d20b2fb200167aa58a"),
"status" : "open",
"hash" : "bef5f50628b669b9930b89cdc040361b9c8cc2b4aab3c2059c171786d38d507e"
},
{
"_id" : ObjectId("611bb4d20b2fb200167aa58b"),
"status" : "open",
"hash" : "1b4a91eb5de97d6ad7493b6e1ffa48a2a648084b4af7b37916c723533a07c37c"
},
{
"_id" : ObjectId("611bb4d20b2fb200167aa58c"),
"status" : "open",
"hash" : "bb64ba7b2612856dcd95c3ac2fad3f7368e5d463168545b12f4c869af56b55b7"
},
{
"_id" : ObjectId("611bb4d20b2fb200167aa58d"),
"status" : "open",
"hash" : "1d5fc04739b10414dea8d327998df4f200f47ce57da243bd578d4ae102f2d670"
},
{
"_id" : ObjectId("611bb4d20b2fb200167aa58e"),
"status" : "open",
"hash" : "d5368ad5658ec11103796255d127d26da7f3324cdedbd124bdd5db50812d588e"
},
{
"_id" : ObjectId("611bb4d20b2fb200167aa58f"),
"status" : "open",
"hash" : "37298229097785ebc9d419cc1a3f13e0d090a15ceb9a8e6bea3505366902556d"
},
{
"_id" : ObjectId("611bb4d20b2fb200167aa590"),
"status" : "open",
"hash" : "fad290f2ddd0e097e4098c3b2c3d65611406cf208a3f86924d45c7736393b44b"
}
]
}
And the is my result:
Updated 0 record(s) in 12ms
Thank you!
You have to use arrayFilters in this way:
db.collection.update({
"name": "test"
},
{
"$set": {
"issues.$[element].status": "closed"
}
},
{
"arrayFilters": [
{
"element.hash": {
"$nin": [
"8ff28fcc9cbf10c9b690bb331e5609efbd3c526be4f536ebca02cc51bd63eac7",
"d5368ad5658ec11103796255d127d26da7f3324cdedbd124bdd5db50812d588e",
"37298229097785ebc9d419cc1a3f13e0d090a15ceb9a8e6bea3505366902556d",
"fad290f2ddd0e097e4098c3b2c3d65611406cf208a3f86924d45c7736393b44b"
]
}
}
]
})
Example here.
Note that update query has the format: update(query, update, options) (Check the docs).
So with your find query mongo doesn't find anything. Check this example.
This is why you are telling mongo: "Give me a DOCUMENT where name is test and issues array NOT contains a field called hash with these values".
So, as mongo search by the whole document, there is no any document where hash value is not on the $nin array.
As another example to exaplain better: Check this example where hash value is 1. In this case, find query works because it matches two conditions:
There is a field name with value test
There is not any field hash into issues with values into $nin array.
You can use arrayFilters, like this:
db.collection.update({
"name": "test"
},
{
"$set": {
"issues.$[elem].status": "closed"
}
},
{
"multi": true,
"arrayFilters": [
{
"elem.hash": {
"$nin": [
"8ff28fcc9cbf10c9b690bb331e5609efbd3c526be4f536ebca02cc51bd63eac7",
"d5368ad5658ec11103796255d127d26da7f3324cdedbd124bdd5db50812d588e",
"37298229097785ebc9d419cc1a3f13e0d090a15ceb9a8e6bea3505366902556d",
"fad290f2ddd0e097e4098c3b2c3d65611406cf208a3f86924d45c7736393b44b"
]
}
}
]
})
Here is the working example: https://mongoplayground.net/p/8wZkmlBgKiq

$pull operator in MongoDB

{
"_id" : ObjectId("5badfada90fd543fd8aa7f96"),
"__v" : 0,
"deleted" : false,
"groups" : [
{
"group" : "grp",
"_id" : ObjectId("5bae09a601123357e58b66a2"),
"activities" : [
ObjectId("5bae09a601123357e58b66a3"),
ObjectId("5bae10de01123357e58b66a6")
]
},
{
"group" : "123",
"_id" : ObjectId("5bae0f1001123357e58b66a4"),
"activities" : [
ObjectId("5bae0f1001123357e58b66a5")
]
}
],
"nextActivityId" : 22,
"name" : "test",
"year" : "1",
"status" : "2",
"vision" : ObjectId("5bab2f4872acf42a81c124d0")
}
The Above Schema is a "Plan" Schema
I have to write a query for removing an Activity inside "activities" array. What will be the optimum solution for this? And how will I use $pull to achieve this
This was my solution, but it will delete the complete groups array
Plan.update({ _id: PLAN ID }, { $pull: { groups: { activities: ACTIVITY ID } } })
PLAN ID BEING: "_id" : ObjectId("5badfada90fd543fd8aa7f96"),
ACTIVITY ID FOR EXAMPLE BEING: ObjectId("5bae09a601123357e58b66a3")
Thank you!
You need to use the positional $ update operator.
db.Plan.update(
{ "_id" : PLAN ID },
{ "$pull": { "groups.$.activities": ACTIVITY ID } }
)
You can try this,
db.Plan.update({ _id: ObjectId("5badfada90fd543fd8aa7f96"),"groups.activities":{$in:[ ObjectId("5bae09a601123357e58b66a3") ]}},
{ $pull: { "groups.$.activities": ObjectId("5bae09a601123357e58b66a3") } });
The positional operator did not find the match needed from the query warning when use $ only update object.

MongoDB update Query in a loop

I am working with MongoDB in one of my project. For the next feature I need to add a flag to array of objects by looping with a matching condition.
Following is an example of document that I have -
{
"_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
"colors" : [
{ "status" : "done" },
{ "status" : "done" },
{ "status" : "n/a" }
]
}
Output should be -
{
"_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
"colors" : [
{
"status" : "done",
"is_in_production" : true
},
{
"status" : "done",
"is_in_production" : true
},
{
"status" : "n/a"
}
]
}
I used the following query -
db.getCollection('products').update(
{
"colors.status": {
"$in":[
"done"
]
}
},
{$set: { 'colors.$[].is_in_production' :true }},
{multi: true}
)
That resulted the following error -
cannot use the part(colors of colors.$[].is_in_production)totraversetheelement({ colors: [{ "status" : "done" }, { "status" : "done" }, { "status" : "n/a" }] )}
Can someone help me with the query?? Thanks in Advance
Use updateMany together with arrayFilters to update multiple documents in an array
db.products.updateMany(
{ "colors.status": "done" },
{ $set: { "colors.$[element].is_in_production" : true}},
{ arrayFilters: [{"element.status" : "done"}]}
)
Use arrayFilters to update only a subset of embedded documents.
Try this query:
db.products.update(
{
"colors.status": {
"$in":[
"done"
]
}
},
{$set: { 'colors.$[element].is_in_production' :true }},
{multi: true, arrayFilters:[{"element.status":"done"}]}
)
Output is:
/* 1 */
{
"_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
"colors" : [
{
"status" : "done",
"is_in_production" : true
},
{
"status" : "done",
"is_in_production" : true
},
{
"status" : "n/a"
}
]
}
Note that you need MongoDB 3.6 and need to execute on latest shell (no third party tools preferably) in order for the arrayFilters to work properly.
If the above query isn't working for your Mongo version, try this query:
db.sample.findAndModify({
query:{
"colors.status": {
"$in":[
"done"
]
}
},
update:{$set: { 'colors.$[element].is_in_production' : true }},
multi: true,
arrayFilters:[{"element.status":"done"}]
})

Mongo DB - Group By and Having Implementation

I'm trying to write a Mongo DB query where I do the following,
JSON list - Representing documents in my collection,
Industry[]:
{
"_id" : ObjectId("57aa6058be0c853c8cee34cd"),
"options": {
"paramList" : [
{
"name" : "industryCategory",
"value" : "Travel",
"mandatory" : true
},
{
"name" : "someOtherThing",
"value" : "dontMind",
"mandatory" : true
}
]
}
"mostRecent" : true
},
{
"_id" : ObjectId("57aa6058be0c853c8cee34cd"),
"options": {
"paramList" : [
{
"name" : "industryCategory",
"value" : "Dining",
"mandatory" : true
},
{
"name" : "someOtherThing",
"value" : "dontMind",
"mandatory" : true
}
]
}
"mostRecent" : true
},
{
"_id" : ObjectId("57aa6058be0c853c8cee34cd"),
"options": {
"paramList" : [
{
"name" : "industryCategory",
"value" : "Travel",
"mandatory" : true
},
{
"name" : "someOtherThing",
"value" : "dontMind",
"mandatory" : true
}
]
}
"mostRecent" : true
}
I'm trying to group and get a count of values for those paramList - values where name is industryCategory. Essentially, the output I am looking for is something like this,
Travel: 2
Dining: 1
I'm trying to do the following,
Industry is the name of the collection,
db.Industry.aggregate (
[
{$match: {mostRecent: true}},
{$group: {
_id: '$options.paramList.value',
count: {$sum: 1}
}},
{$match: {'options.paramList.name': 'industryCategory'}}
])
I'm getting an empty result. Please suggest what I can do
Well, I didn't have anyone answering. But, in the meanwhile I managed to figure it out myself. Posting the answer below,
aggregate (
[
{"$match": {mostRecent: true}},
{"$unwind" : "$options.paramList"},
{"$group" :
{
_id: "$options.paramList.value",
count: {$sum : 1}
}
}
]
Essentially, use unwind wherever you have to iterate over arrays (a list of sub-documents). This has been a productive learning, at least for me.