Edo
Edo

Reputation: 1589

Update on a subset of embedded documents in MongoDB

Given the following db

{
    "type":"s",
    "disp":[
        {
            "quantity":1,
            "date":20141109
        },
        {
            "quantity":1,
            "date":20141110
        },
        {
            "quantity":1,
            "date":20141111
        }
    ]
},
{
    "type":"d",
    "disp":[
        {
            "quantity":1,
            "date":20141109
        },
        {
            "quantity":0,
            "date":20141110
        },
        {
            "quantity":1,
            "date":20141111
        }
    ]
}

I perform a query to obtain a "type" with quantity grater then 0 for a set of dates

db.test.find({ "$and" : [
    { "disp" : { "$elemMatch" : { "quantity" : { "$gt" : 0 }, "date" : 20141109 } } },
    { "disp" : { "$elemMatch" : { "quantity" : { "$gt" : 0 }, "date" : 20141110 } } }
] },{"type":1})

I get the type "s" then I want to decrement by 1 only the quantity for the dates I just queried

I tried different kinds of update queries but I was able to change just one quantity field.

How can I do that in an atomic way ? If it's not possible can you advise me on a way to structure my data to query and atomically update quantity for specific dates ?

Upvotes: 1

Views: 239

Answers (1)

BatScream
BatScream

Reputation: 19700

You can update only a single matching sub document in MongoDb, even if multiple sub documents match the query. Currently it is a limitation.

To update all the sub documents for each date, you need to fire n update queries to update documents for n different matching dates.

You need to make use of the $inc and the positional update $ operators.

var dates = [20141109,20141110];
dates.forEach(function(date){
db.test.update({"type":"s","disp.date":date},
                     {$inc:{"disp.$.quantity":1}})
})

Answering your questions:

atomically update quantity for specific dates

As per the documentation,

$inc is an atomic operation within a single document.

A suggestion:

n a way to structure my data to query

Never have two different sub documents for the same date as depicted in the example. If you would have then it makes no sense in updating two different sub documents for the same date.

    {
        "quantity":0,
        "date":20141110
    },
    {
        "quantity":1,
        "date":20141110
    }

Upvotes: 1

Related Questions