DwayneBull
DwayneBull

Reputation: 264

MongoDB upsert with $push and $not

I've recently updated to Mongodb 2.2.0 and found that the following query now no longer works.

The database is empty and I run the following:

db.Sessions.update({_id:"test",sessions:{$not:{$elemMatch:{type:"Web"}}}},{$push:{sessions:{type:"Web",dateAdded:new Date}}},true)

returns the error:

Cannot apply $push/$pushAll modifier to non-array

Prior to the update the following document would have been created:

{ "_id" : "test", "sessions" : [ { "type" : "Web", "dateAdded" : ISODate("2012-09-12T15:11:11.942Z") } ] }

Any ideas?

Edit: I forgot to mention, it's the addition of the $not that breaks in this version as the following works fine, so it's not a issue that the array/field doesn't exist.

db.Sessions.update({_id:"test"},{$push:{sessions:{type:"Web",dateAdded:new Date}}},true)

Upvotes: 2

Views: 3862

Answers (2)

James Hartig
James Hartig

Reputation: 1009

I filed a bug "a query field with a $not operator should not be used to populate an upsert document" which will be backported into 2.2.x that fixes this situation.

Upvotes: 2

friedo
friedo

Reputation: 67048

The behavior of $elemMatch has changed slightly in 2.2, which is why this no longer works in combination with $not, which is only a meta-operator for negating other operators and can not actually be used to search fields.

Instead, you can use $nin (not in) to inspect the values inside your sessions array.

For example,

> db.Sessions.update( { _id:"test", sessions: { "$nin": {type: "Web"} } }, {"$push":{sessions:{type:"Web",dateAdded:new Date}}},true);
> db.Sessions.findOne();
{
    "_id" : "test",
    "sessions" : [
        {
            "type" : "Web",
            "dateAdded" : ISODate("2012-09-12T16:03:18.271Z")
        }
    ]
}

Upvotes: 3

Related Questions