2

I am fairly new to MongoDB and cant seem to find a solution to this problem. I have a database of documents that has this structure:

   {
      id: 1 
      elements: [ {elementId: 1, nr1: 1, nr2: 3}, {elementId:2, nr1:5, nr2: 10} ]
   }

I am looking for a query that can add a value nr3 which is for example nr2/nr1 to all the objects in the elements array, so that the resulting document would look like this:

  {
      id: 1 
      elements: [ {elementId: 1, nr1: 1, nr2: 3, nr3:3}, {elementId:2, nr1:5, nr2: 10, nr3: 2} ]
   }

So I imagine a query along the lines of this:

db.collection.updateOne({id:1}, {$set:{"elements.$[].nr3": nr2/nr1}})

But I cant find how to get the value of nr2 and nr1 of the same object in the array. I found some similar questions on stackoverflow stating this is not possible, but they were 5+ years old, so I thought maybe they have added support for something like this.

I realize I can achieve this with first querying the document and iterate over the elements-array doing updates along the way, but for the purpose of learning I would love to see if its possible to do this in one query.

2 Answers 2

3

You can use update with aggregation pipeline starting from MongoDB v4.2,

  • $map to iterate loop of elements
  • divide nr2 with nr1 using $divide
  • merge current object and new field nr3 using $mergeObjects
db.collection.updateOne(
  { id: 1 }, 
  [{
    $set: {
      elements: {
        $map: {
          input: "$elements",
          in: {
            $mergeObjects: [
              "$$this",
              { nr3: { $divide: ["$$this.nr2", "$$this.nr1"] } }
            ]
          }
        }
      }
    }
  }]
)

Playground

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! Alas, I have new fields in my array elements. :)
0

db.collection.update(
  { id:1},
  { "$set": { "elements.$[elem].nr3":elements.$[elem].nr2/elements.$[elem].nr1} },
  { "multi": true }
);

I guess this should work

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.