Update last element of an array that match a consition, using $ positional operator

844 views
Skip to first unread message

DDany

unread,
Apr 5, 2012, 5:53:13 AM4/5/12
to mongod...@googlegroups.com
Hi,
in order to do what I wrote on the subject, I read about the "$ positional operator" here http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator

As the subject say, what I would like to do, is to update only the last element of an array that matches a criteria.
I try to explain better. Let's say I have a doc like this:
{
"_id" : ObjectId("4f7d6606eaf4566192d7c923"),
"x" : [
{
"a" : "1",
"value" : 2
},
{
"a" : "2",
"value" : 2
},
{
"a" : "2",
"value" : 3
}
]
}

I'd like to update the value field of the second x element having a= 2.
By doing    db.prova.update({"x.a":"2"},{$set:{'x.$.value':4}})  I see the first element is updated.

"_id" : ObjectId("4f7d6606eaf3806192d7c923"),
"x" : [
{
"a" : "1",
"value" : 2
},
{
"a" : "2",
"value" : 4
},
{
"a" : "2",
"value" : 3
}
]

I would like to avoid to extract the array, change it at application level, and then update he entire x field.
Could someone suggest a way to do it directly via mongo?

Thanks in advance to anyone who will answer, 
bye

mathias

unread,
Apr 5, 2012, 11:42:55 AM4/5/12
to mongodb-user
Unfortunately this is not possible to do this directly with the $
positional operator since it only updates the first matching element
of the array. One workaround you can use is to reverse the order of
the array so the first element is the one you want to update. The only
two other options are to update by index and to replace the whole
array. You can use a version field to "update-if-current" if the
atomic guarantees are important to you:
http://www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-%22UpdateifCurrent%22

On Apr 5, 5:53 am, DDany <ddan...@gmail.com> wrote:
> Hi,
> in order to do what I wrote on the subject, I read about the "$ positional
> operator"
> herehttp://www.mongodb.org/display/DOCS/Updating#Updating-The%24positiona...

DDany

unread,
Apr 6, 2012, 3:48:06 AM4/6/12
to mongod...@googlegroups.com
Hi Mathias, 
first of all thanks for your answer.
To reverse the order of the array is something I thought about too,
so, always trying to do operation via mongoDB, i looked for a way tu "push"
an element in the top of an array field, but I found nothing.

To do what I wrote above, the only way is to replace the entire array when I insert
a new element. 
Am I right? Or there's a smarter way to do it?

Bye

Mathias Stearn

unread,
Apr 6, 2012, 2:40:52 PM4/6/12
to mongod...@googlegroups.com
The only other option is to determine the index of the item in the array you want to modify and use that:

db.foo.update({_id:...}, {$set: {x.2.value: 1234}})

Glenn Maynard

unread,
Apr 6, 2012, 4:30:40 PM4/6/12
to mongod...@googlegroups.com
A syntax that could be used to support this directly would be:

db.foo.update({...}, {$set: {'x.$match[0].y'': 1}});

where $match[N] refers to the N'th match, with negative values being offsets from the end, like Python indexing.  Out-of-bounds values would raise an error.

This would align with the $idx[n] syntax proposed in SERVER-4753.

(I don't personally need this at the moment, so I won't file a ticket for it.  I havn't looked to see if there's already a ticket similar to this.)

--
Glenn Maynard

Carlos Jose

unread,
Apr 25, 2013, 12:33:12 PM4/25/13
to mongod...@googlegroups.com


the correct sintax db.prova.update({"x.a":"2","x.value":"3"},{$set:{'x.$.value':4}}) 
Reply all
Reply to author
Forward
0 new messages