agnsaft
agnsaft

Reputation: 1881

Mongodb upsert only update selected fields, but insert all

I am trying to use upsert in MongoDB to update a single field in a document if found OR insert a whole new document with lots of fields. The problem is that it appears to me that MongoDB either replaces every field or inserts a subset of fields in its upsert operation, i.e. it can not insert more fields than it actually wants to update.

What I want to do is the following:

Lets illustrate:

This example would from my understanding update the 'lastseen' date if 'name' is found, but if 'name' is not found it would only insert 'name' + 'lastseen'.

db.somecollection.update({name: "some name"},{ $set: {"lastseen": "2012-12-28"}}, {upsert:true})

If I added more fields (key/value pairs) to the second argument and drop the $set, then every field would be replaced on update, but would have the desired effect on insert. Is there anything like $insert or similar to perform operations only when inserting?

So it seems to me that I can only get one of the following:

Are my understanding correct? If so, is this possible to solve with a single operation?

Upvotes: 17

Views: 20095

Answers (2)

cerberos
cerberos

Reputation: 8035

MongoDB 2.4 has $setOnInsert

db.somecollection.update(
    {name: "some name"},
    {
        $set: {
            "lastseen": "2012-12-28"
        },
        $setOnInsert: {
            "firstseen": <TIMESTAMP>  # set on insert, not on update
        }
    },
    {upsert:true}
)

Upvotes: 39

Sammaye
Sammaye

Reputation: 43884

There is a feature request for this ( https://jira.mongodb.org/browse/SERVER-340 ) which is resolved in 2.3. Odd releases are actually dev releases so this will be in the 2.4 stable.

So there is no real way in the current stable versions to do this yet. I am afraid the only method is to actually do 3 conditional queries atm: 1 to check the row, then a if to either insert or update.

I suppose if you had real problems with lock here you could do this function with sole JS but that's evil however it would lock this update to a single thread.

Upvotes: 8

Related Questions