1

I am trying to update an object into an array in MongoDB.
Here are my documents :

> db.devis.insert({id:1,obj:[{'code':'A'},{'code':'B'}]})  
> db.devis.insert({id:2,obj:[{'code':'C'},{'code':'D'}]})  

> db.devis.find()
[
  {
    id: 1,
    obj: [ { code: 'A' }, { code: 'B' } ]
  },
  {
    id: 2,
    obj: [ { code: 'C'}, { code: 'D' } ]
  }
]

I select the document with the code 'B'.
I can add one field with this command :

> db.devis.update({'obj.code':'B'},{$set: {'obj.$.a':'a'}})  

# Result
{
  id: 1,
  obj: [ { code: 'A'}, { code: 'B', a: 'a'} ]
}

Now I want to add several fields :

> var = {'foo':'foo', 'bar':'bar'}
> db.devis.update({'obj.code':'B'},{$set: {'obj.$': var}})

# Result
{
  id: 1,
  obj: [ { code: 'A'}, { foo: 'foo', bar: 'bar'} ]
}

# What I want
{
  id: 1,
  obj: [ { code: 'A'}, { code: 'B', foo: 'foo', bar: 'bar'} ]
}

The object is overwritten.
It is possible to insert in it several fields from a variable ?

2
  • Clarity: You want to keep code but get rid of a and add foo and bar? Commented Nov 10, 2020 at 12:16
  • No the a was just an example to add one field, @J.F. answered exactly what I was looking for. Commented Nov 10, 2020 at 12:33

1 Answer 1

2

The problem here is you are seting the entire object.

When you do {$set: {obj.$:{yourObject}}} you are telling mongo: "Set entire object obj as the object I have passed".

Look at this example

The object with code : B is completly new because your $ operator point at the object and $set will put the new object at this position.

You need this:

db.collection.update({
  "obj.code": "B"
},
{
  "$set": {
    "obj.$.foo": "bar",
    "obj.$.foo2": "bar2"
  }
})

In this case, your $set uses the $ operator to update the field into the object, no the object itself.
In this way you are telling mongo: "Put into the object you have found a variable called 'foo' with value 'bar' and another variable 'foo2' with value 'bar2'"

I hope I have explained well to note the difference between the two queries.

So, no tested, but using:

var = {'obj.$.foo':'foo', 'obj.$.bar':'bar'}
db.devis.update({'obj.code':'B'},{$set: var})

Should works.

Example here

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

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.