Update specific element in nested array - mongodb

I have the following structure
{
"_id":"5b609d1a5b4e2c03e512992b",
"files_missing":5,
"files_rejected":0,
"userId":"5afcbbcf26d784ca35fac580",
"files":[
{
"status":"sent",
"_id":"5b609d1a5b4e2c03e5129930",
"fileId":"5afcbad526d784ca35fac576",
"urls" [
{
"_id":"5b60e10114bce7084cebc1da",
"file":"/data/5b609d195b4e2c03e512992a.pdf",
"status":"sent"
},{
"_id":"5b60e1ea14bce7084cebc1dd",
"file":"/data/5b60e1ea14bce7084cebc1dd.pdf",
"status":"sent"
}
]
}
],
"contactId":"5b609d195b4e2c03e512992a",
"created_at":"2018-07-31T17:32:10.251Z",
"updated_at":"2018-07-31T17:32:10.251Z",
}
And I want to update the status inside in one of the elements of urls
I tried:
db.collection.update({contactId:"5b609d195b4e2c03e512992a",
'files.urls._id': "5b60e1ea14bce7084cebc1dd"},{$set:
{'files.urls.$.status': 'rejected'}})
MongoDB version: 3.2.17

Related

MongoDB and Flask - Updating objects in a document's array (nested updating)

Assume we have following collection.
{
"Region":"Karnataka",
"ShortCode":"KA",
"SubRegion":[
{
"District":"Banglore",
"Commodity":[
{
"Name":"items",
"isActive":true,
"CommoditySubType":[
{
"Title":"Moistouriser",
"isActive":true,
"hasGrades":true,
"Grade":[
{
"Title":"Premium",
"Rate":"150",
"isActive":true,
"hasRates":true,
"hasSizes":true,
"StartDate":"2021-03-31",
"EndDate":"2021-04-06",
"StartTime":"9:00am",
"EndTime":"6:00pm",
"Sizes":[
{
"Title":"Small",
"isActive":true
}
]
"LastSevenDaysDates":[{
"Date":2021-03-31,
"Price":"150"
}]
}
]
}
]
}
]
},
{
"District":"Coorg",
"Commodity":[]
}
] }
I want to update an object under LastsevndayDates. I tried this.
mongo.db.supplierDailyPrice.update(
{
"Region":region,
"SubRegion.District":district,
"SubRegion.Commodity.Name":commodity,
"SubRegion.Commodity.CommoditySubType.Title":commoditysubtype,
"$and": [
{ "SubRegion.Commodity.CommoditySubType.Grade": { "$exists": True}},
{ "SubRegion.Commodity.CommoditySubType.Grade.Title": "Premium" },
]
},
{
"$set": {
"SubRegion.$[].Commodity.$[].CommoditySubType.$[].Grade.$[].LastSevenDaysDates": Date
}
})
But it's failing with the error pymongo.errors.WriteError: The path 'SubRegion.0.Commodity.0.CommoditySubType.1.Grade' must exist in the document in order to apply array updates.
You can use arrayFilters to solve your problem
db.supplierDailyPrice.update({
"Region":region
},
{
$set:{
"Subregion.$[sub].Commodity.$[com].CommoditySubType.$[Cst].Grade.$[grd]. LastSevenDaysDates.$[sev].date": Date
}
},
{
array_filter : [
{"sub.district": district},
{"com.name": commodity},
{"Cst.title": commoditysubtype},
{"grd.title": "premium"},
{"sev.price":"150"},
]
})
Not tested the code but something like this will solve your problem. For more reference you can check out the links below:
Update deeply nested array in mongodb
update deeply nested array mongodb
Pymongo error for ArrayFilters to update multiple subdocuments
Ujjwal's answer is on the right track. I fixed a few typos.
More information here about $[] usage.
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/
https://developer.mongodb.com/how-to/update-array-elements-document-mql-positional-operators/
db.supplierDailyPrice.update_one({
"Region": region
},
{
$set:{
"SubRegion.$[sub].Commodity.$[com].CommoditySubType.$[cst].Grade.$[grd].LastSevenDaysDates.$[sev].Date": "2021-04-03"
}
},
{
"array_filters" : [
{"sub.District": district},
{"com.Name": commodity},
{"cst.Title": commoditysubtype},
{"grd.Title": grade},
{"sev.Price":"150"},
]
},
{
upsert=true
}
)

Sort records based on nested array element in MongoDB

I have modal something like this
[{
"_id":"",
"document_name":"Document 1",
"document_users" : [
{
"name":"Jhon",
"email":"jhon#gmail.com",
"added_at":"2020-12-11 10:30:01"
},
{
"name":"Michel",
"email":"michel#gmail.com",
"added_at":"2020-12-11 10:40:00"
}
]
},
{
"_id":"",
"document_name":"Document 2",
"document_users" : [
{
"name":"Jhon",
"email":"jhon#gmail.com",
"added_at":"2020-12-12 10:30:01"
},
{
"name":"Henry",
"email":"henry#gmail.com",
"added_at":"2020-12-14 10:40:00"
}
]
}]
I need to sort this main documents records based on particular user's "added_at" in the "document_users". Here email id is unique in the "document_users" field.
In nutshell, sort the main documents based on nested elements.
It will be great if I get any help how to write the mongoDB query for this one

MongoDB update array object filed with value of another field of that same object array

I have a collection like the following:
{
_id: asilu92834,
services: [
{
chargeAmount: 10,
calculatedChargeAmount: 5,
},
{
chargeAmount: 20,
calculatedChargeAmount: 15,
}
]
}
what I am trying to do is to update the chargeAmount field with it's object's value of calculatedChargeAmount field. After the update the doc should look like the following:
{
_id: asilu92834,
services: [
{
chargeAmount: 5,
calculatedChargeAmount: 5,
},
{
chargeAmount: 15,
calculatedChargeAmount: 15,
}
]
}
I know how to update this after reading each doc and then update them one at a time with forEach. that's not what I want.
I know that updateMany() function accepts aggregate pipelines and in those pipelines you should be able to do something like
[
{ $set: { "value1": "$value2"}}
]
but since chargeAmount and calculatedChargeAmount is nested inside and array of objects I tried to do this
db.collection.updateMany(filter, [
{
$set: {
'services.$[].chargeAmount': '$services.$[].calculatedChargeAmount'
}
}
]);
I get error saying FieldPath field names may not start with '$'. Is it not possible to do what I am trying to achieve? if so how?
Try this instead:
db.collection.updateMany({"services._id":req.user.id},
{$set: {"services.$.chargeAmount" :'services.$.calculatedChargeAmount'}},
function (error, success) {
if(error)
{
console.log(error);
}
else {
console.log('success');
}
})
Remember, here id is the _id for the array services in mongoDB. It must be having one _id automatically got created.

Mongo: select only one field from the nested object

In mongo I store object that have field "titleComposite". This field contains array of title object, like this:
"titleComposite": [
"0": {
"titleType": "01",
"titleText": "Test cover uploading"
}
]
I'm perfoming query and I would like to receive only "titleText" value for the returned values. Here is an example of my query:
db.onix_feed.find({"addedBy":201, "mediaFileComposite":{$exists:false}}, {"isbn13":1,"titleComposite.titleText":1})
In the results I see values like
{
"_id" : ObjectId("559ab286fa4634f309826385"),
"titleComposite" : [ { "titleText" : "The Nonprofit World" } ],
"isbn13" : "9781565495296"
}
Is there any way to get rid of "titleComposite" wrapper object and receive only titleText? For example, take titleText of the first element only?
Would appreciate any help
You can mongodb aggregation to achieve your expected result. Re-arrange your query as following...
db.onix_feed.aggregate([
{
$match: {
$and: [
{"addedBy":201},
{"mediaFileComposite":{$exists:false}}
]
}
},
{
$project : { titleText: "$titleComposite.titleText",
"isbn13" : 1 }
}
])

mongodb update push sub-subdocument

The question is quite easy. I have the following document in mongoDb:
_id : ObjectId("519e3c14ade67153e9a003a0")
status:1,
name:"name",
details:
{
crm:115,
webs:
[
{ tag:"blog" , url:"http://..."}
],
contacts:
[
{
_id:ObjectId("009e37e1ade67153e9a0039e"),
name:"me",
phones:
[
{ tag:"home", number:"123..." },
{tag:"mobile", number:"123456789"}
]
}
]
}
I am trying to update one fo the phones in the subdocument details.contacts doing this:
db.new.update(
{
_id : ObjectId("519e3c14ade67153e9a003a0"),
"details.contacts._id": ObjectId("009e37e1ade67153e9a0039e"),
"details.contacts.phones.tag":"home"
},
{
$set:
{
"details.contacts.$.phones.$":
{
tag:"home",
number:"965923777"
}
}
})
and finally I get the following error: Cannot apply the positional operator without a corresponding query field containing an array.
There is anyway to update the document in this way or i should send all the phones to update this field?