Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can mongo upsert array data?

I have a mongo document like this.

{     "_id" : ObjectId("50b429ba0e27b508d854483e"),     "array" : [         {             "id" : "1",             "letter" : "a"         },         {             "id" : "2",             "letter" : "b"         }     ],     "tester" : "tom" } 

I want to be able to insert and update the array with a single mongo command and not use a conditional within a find() then run insert() and update() depending on the presence of the object.

The id is the item I want to be the selector. So if I update the array with this:

{     "id" : "2",     "letter" : "c" } 

I have to use a $set statement

db.soup.update({     "tester":"tom",     'array.id': '2' }, {     $set: {         'array.$.letter': 'c'     } }) 

And if I want to insert a new object into the array

{     "id" : "3",     "letter" : "d" } 

I have to use a $push statement

db.soup.update({     "tester":"tom" }, {     $push: {         'array': {             "id": "3",             "letter": "d"         }     } }) 

I need a sort of upsert for an array item.

Do I have to do this programmatically or can I do this with a single mongo call?

like image 831
ThomasReggi Avatar asked Nov 27 '12 16:11

ThomasReggi


People also ask

Does MongoDB support Upsert?

Here in MongoDB, the upsert option is a Boolean value. Suppose the value is true and the documents match the specified query filter. In that case, the applied update operation will update the documents. If the value is true and no documents match the condition, this option inserts a new document into the collection.

How do I update an entire array in MongoDB?

You can use the updateOne() or updateMany() methods to add, update, or remove array elements based on the specified criteria. It is recommended to use the updateMany() method to update multiple arrays in a collection.

Does MongoDB support array?

Unlike relational database models, MongoDB documents can have fields which have values as arrays. The prototypical example in almost all MongoDB documentation is a document having a tags field, whose value is an array of strings, such as ["NoSQL", "Ruby", "MongoDB"] .

How do I update a nested array in MongoDB?

Update Nested Arrays in Conjunction with $[]The $[<identifier>] filtered positional operator, in conjunction with the $[] all positional operator, can be used to update nested arrays. The following updates the values that are greater than or equal to 8 in the nested grades. questions array if the associated grades.


2 Answers

I'm not aware of an option that would upsert into an embedded array as at MongoDB 2.2, so you will likely have to handle this in your application code.

Given that you want to treat the embedded array as sort of a virtual collection, you may want to consider modelling the array as a separate collection instead.

You can't do an upsert based on a field value within an embedded array, but you could use $addToSet to insert an embedded document if it doesn't exist already:

db.soup.update({     "tester":"tom" }, {     $addToSet: {         'array': {             "id": "3",             "letter": "d"         }     } }) 

That doesn't fit your exact use case of matching by id of the array element, but may be useful if you know the expected current value.

like image 92
Stennie Avatar answered Oct 16 '22 05:10

Stennie


I just ran into this problem myself. I wasn't able to find a one-call solution, but I found a two-call solution that works when you have a unique value in your array elements. Use the $pull command first, which removes elements from an array, and then $push.

db.soup.update({     "tester":"tom" }, {     $pull: {         'array': {             "id": "3"         }     } }) db.soup.update({     "tester":"tom" }, {     $push: {         'array': {             "id": "3",             "letter": "d"         }     } }) 

This should work when the document doesn't exist, when the document exists but the entry in the array doesn't exist, and when the entry exists.

Again, this only works if you have something, like the id field in this example, that should be unique across elements of the array.

like image 39
Rob Watts Avatar answered Oct 16 '22 05:10

Rob Watts