1

Lets say there is an object like this in the db:

{
    _id: <...>,
    arrayOfObjects: [
        {
            criteria: "one",
            value: 5
        },
        {
            criteria: "two",
            value: 5
        },
        {
            criteria: "three",
            value: 5
        },
        {
            criteria: "four",
            value: 5
        },

    ]
}

What I want to do is to run an update similar to:

{
    $inc: {
        "arrayOfObjects.2.value" : -1
    }
}

However I need it to affect only certain elements, e.g. {$or: [{criteria: "one"}, {criteria: "three"}]} I cannot rely on array indexes as the object copy I have may have expired before the update is executed (objects can be inserted, deleted, rearranged in the array).

Is it possible to pull this off? What would be the optimal way to do this?

3 Answers 3

1

You would have to do this as two separate update commands, because the $ positional operator only identifies the first array element matched:

db.coll.update({_id: <...>, 'arrayOfObjects.criteria': 'one'},
    {'arrayOfObjects.$.value': {$inc: -1}})
db.coll.update({_id: <...>, 'arrayOfObjects.criteria': 'three'},
    {'arrayOfObjects.$.value': {$inc: -1}})
Sign up to request clarification or add additional context in comments.

Comments

0

Use this query

{$or: [{arrayOfObjects.criteria: "one"}, {arrayOfObjects.criteria: "three"}]}

For your update

EDIT:

Try this

collectionName.update({arrayOfObjects.criteria: "one"}, {$inc: {"arrayOfObjects.$.value" : -1}}, false, true);

collectionName.update({arrayOfObjects.criteria: "three"}, {$inc: {"arrayOfObjects.$.value" : -1}}, false, true);

Also, have a look at this link for more info on mongodb updates http://www.mongodb.org/display/DOCS/Updating#Updating-update%28%29

Edited my answer.

@JohnnyHK is right. It requires 2 queries. My bad. It's late and I'm tired :)

2 Comments

I'm sorry, I couldn't make out the query. Would you care to write an actual example of how this would look like in the js client?
Sorry, but your example does not work and I fail to see how it could. The query part of the update selects the whole document and believe there is no way to select only a part of the document for an update like you tried here
0

I do no know what why exactly you can not run Michai's query, because in my opinion it is correct. So I am posting my answer. First of all, you can not do this in one query. Yes, sounds ridiculous but here is the thing : https://jira.mongodb.org/browse/SERVER-1243

May this is a good idea to write or upvote this issue there and may be in next few months they will solve it. But judging by the creating time of the post 2010 I highly doubt that :-(

So here are some workarounds how you can do it: First of all if there are not a lot of criteria than you can do this using multiple queries:

db.coll.update({
  _id: <...>,
  'arrayOfObjects.criteria': 'Criteria 1'
}, {
  'arrayOfObjects.$.value': {
     $inc: -1
   }
})

and doing this as many times as you have different criteria.

But if there are too many criteria it you can waste too many queries. So you will be able to do this in two queries in any case.

  1. reading the object based on your criteria. db.coll.find( {'arrayOfObjects.criteria' : { $in: ['one', 'three'] }})
  2. modify it at your application level
  3. save it in mongo

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.