I'm trying to update a field (totalPrice) in my document(s) based on a value in a nested, nested array (addOns > get matching array from x number of arrays > get int in matching array[always at pos 2]).
Here's an example of a document with 2 arrays nested in addOns:
{
"_id": ObjectID('.....'),
"addOns": [
["appleId", "Apples", 2],
["bananaID", "Bananas", 1]
],
"totalPrice": 5.7
}
Let's say the price of bananas increased by 20cents, so I need to look for all documents that have bananas in its addOns, and then increase the totalPrice of these documents depending on the number of bananas bought. I plan on using a updateMany() query using an aggregation pipeline that should roughly look like the example below. The??? should be the number of bananas bought, but I'm not sure how to go about retrieving that value. So far I've thought of using $unwind, $filter, and $arrayElemAt, but not sure how to use them together. Would appreciate any help!
db.collection('orders').updateMany(
{ $elemMatch: { $elemMatch: { $in: ['bananaID'] } } },
[
{ $set: {'totalPrice': { $add: ['$totalPrice', { $multiply: [{$toDecimal: '0.2'}, ???] } ] } } }
]
I'm not exactly sure whats my mongo version is, but I do know that I can use the aggregation pipeline because I have other updateMany() calls that also use the pipeline without any issues, so it should be (version >= 4.2).
** Edit : Thought of this for the???, the filter step seems to work somewhat as the documents are getting updated, but the value is null instead of the updated price. Not sure why
{ $arrayElemAt: [{ $arrayElemAt: [ { $filter: { input: "$addOns", as:'this', cond: { $eq: ['$$this.0', 'bananaID'] } } } , 0 ] }, 2 ] }
Managed to solve it myself - though only use this if you don't mind the risk of updateMany() as stated by Joe in the question's comments. It's very similar to what I originally shared in ** Edit , except you cant use $$this.0
to access elements in the array.
Insert this into where the??? is and it'll work, below this code block is the explanation:
{ $arrayElemAt: [{ $arrayElemAt: [ { $filter: { input: "$addOns", as:'this', cond: { $eq: [{$arrayElemAt:['$$this', 0]}, 'bananaID'] } } } , 0 ] }, 2 ] }
[["appleId", "Apples", 2], ["bananaID", "Bananas", 1]]
$$this
represents each element in input, and we check whether the first element of $$this
matches 'bananaID'. { $filter: { input: "$addOns", as:'this', cond: { $eq: [{$arrayElemAt:['$$this', 0]}, 'bananaID'] } } }
// how the result from $filter should look like
// [["bananaID", "Bananas", 1]]
// How it looks like after step 3: ["bananaID", "Bananas", 1]
db.collection('orders').updateMany(
{ $elemMatch: { $elemMatch: { $in: ['bananaID'] } } },
[
{ $set: {'totalPrice': { $add: ['$totalPrice', { $multiply: [{$toDecimal: '0.2'}, 1] } ] } } }
], *callback function code*)
// notice how the ??? is now replaced by the quantity of bananas which is 1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.