Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb upsert embedded document

Tags:

mongodb

I have a document per day per meter. How can I add another subdocument in the data array and create the whole document if he doesn't exists ?

{
  "key": "20120418_123456789",
  "data":[
     {
     "Meter": 123456789,
     "Dt": ISODate("2011-12-29T16:00:00.0Z"),
     "Energy": 25,
     "PMin": 11,
     "PMax": 16
     }
  ],
  "config": {"someparam": 4.5}
}

Can I use upsert for that purpose ?

The result will be if document exists :

{
  "key": "20120418_123456789",
  "data":[
     {
     "Meter": 123456789,
     "Dt": ISODate("2011-12-29T16:00:00.0Z"),
     "Energy": 25,
     "PMin": 11,
     "PMax": 16
     },
     {
     "Meter": 123456789,
     "Dt": ISODate("2011-12-29T16:15:00.0Z"),
     "Energy": 22,
     "PMin": 13,
     "PMax": 17
     }
  ],
  "config": {"someparam": 4.5}
}

Thanks in advance

like image 876
hotips Avatar asked Apr 18 '12 09:04

hotips


People also ask

How do I update an embedded file in MongoDB?

Update Documents in an Array The positional $ operator facilitates updates to arrays that contain embedded documents. Use the positional $ operator to access the fields in the embedded documents with the dot notation on the $ operator. You must include the array field as part of the query document.

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.

Is there an Upsert option in the MongoDB insert command?

insert() provides no upsert possibility.

What is the difference between update and Upsert in MongoDB?

In MongoDB, upsert is an option that is used for update operation e.g. update(), findAndModify(), etc. Or in other words, upsert is a combination of update and insert (update + insert = upsert).


1 Answers

I think what you want is the $addToSet command - that will push an element to an array only if it does not already exist. I've simplified your example a bit for brevity:

db.meters.findOne()
{
    "_id" : ObjectId("4f8e95a718bc9c7da1e6511a"),
    "config" : {
        "someparam" : 4.5
    },
    "data" : [
        {
            "Meter" : 123456789,
        }
    ],
    "key" : "20120418_123456789"
}

Now run:

db.meters.update({"key" : "20120418_123456789"}, {"$addToSet": {"data" : {"Meter" : 1234}}})

And we get the updated version:

db.meters.findOne()
{
    "_id" : ObjectId("4f8e95a718bc9c7da1e6511a"),
    "config" : {
        "someparam" : 4.5
    },
    "data" : [
        {
            "Meter" : 123456789,
        },
        {
            "Meter" : 1234
        }
    ],
    "key" : "20120418_123456789"
}

Run the same command again and the result is unchanged.

Note: you are likely going to be growing these documents, especially if this field is unbounded and causing frequent (relatively expensive) moves by updating in this way - you should have a look here for ideas on how to mitigate this:

http://www.mongodb.org/display/DOCS/Padding+Factor#PaddingFactor-ManualPadding

like image 181
Adam Comerford Avatar answered Oct 09 '22 14:10

Adam Comerford