Updating

MongoDB supports atomic, in-place updates as well as more traditional updates for replacing an entire document.

Update

Here's the MongoDB shell syntax for update():

db.collection.update( criteria, objNew, upsert, multi )

Arguments:

  • criteria - query which selects the record to update;
  • objNew - updated object or $ operators (e.g., $inc) which manipulate the object
  • upsert - if this should be an "upsert"; that is, if the record does not exist, insert it
  • multi - if all documents matching criteria should be updated (the default is to only update the first document found)

save() in the mongo shell

The save() command in the mongo shell provides a shorthand syntax to perform a single object update with upsert:

// x is some JSON style object
db.mycollection.save(x); // updates if exists; inserts if new

save() does an upsert if x has no _id field and an insert if it does. Thus, normally, you will not need to explicitly request upserts, just use save().

Upsert means "update if present; insert if missing".

myColl.update( { name: "Joe" }, { name: "Joe", age: 20 }, true );

Modifier Operations

Modifier operations are highly-efficient and useful when updating existing values; for instance, they're great for incrementing a number.

So, while a conventional implementation does work:

var j=myColl.findOne( { name: "Joe" } );
j.n++;
myColl.save(j);

a modifier update has the advantages of avoiding the latency involved in querying and returning the object. The modifier update also features operation atomicity and very little network data transfer.

To perform an atomic update, simply specify any of the special update operators (which always start with a '$' character) with a relevant update document:

db.people.update( { name:"Joe" }, { $inc: { n : 1 } } );

The preceding example says, "Find the first document where 'name' is 'Joe' and then increment 'n' by one."

$inc

{ $inc : { field : value } }

increments field by the number value if field is present in the object, otherwise sets field to the number value.

$set

{ $set : { field : value } }

sets field to value. All datatypes are supported with $set.

$unset

{ $unset : { field : 1} }

Deletes a given field. v1.3+

$push

{ $push : { field : value } }

appends value to field, if field is an existing array, otherwise sets field to the array [value] if field is not present. If field is present but is not an array, an error condition is raised.

$pushAll

{ $pushAll : { field : value_array } }

appends each value in value_array to field, if field is an existing array, otherwise sets field to the array value_array if field is not present. If field is present but is not an array, an error condition is raised.

$pop

{ $pop : { field : 1  } }

removes the last element in an array (ADDED in 1.1)

{ $pop : { field : -1  } }

removes the first element in an array (ADDED in 1.1) |

$pull

{ $pull : { field : _value } }

removes all occurrences of value from field, if field is an array. If field is present but is not an array, an error condition is raised.

$pullAll

{ $pullAll : { field : value_array } }

removes all occurrences of each value in value_array from field, if field is an array. If field is present but is not an array, an error condition is raised.

Upserts

You may use upsert with a modifier operation. In such a case, the modifiers will be applied to the update criteria member and the resulting object will be inserted. The following upsert example may insert the object {name:"Joe",x:1,y:1}.

db.people.update( { name:"Joe" }, { $inc: { x:1, y:1 } }, true );

There are some restrictions. A modifier may not reference the _id field, and two modifiers within an update may not reference the same field, for example the following is not allowed:

db.people.update( { name:"Joe" }, { $inc: { x: 1 }, $set: { x: 5 } } );

Pushing a Unique Value

To add a value to an array only if not already present, add $ne : <value> to your query expression:

update( {_id:'joe', tags: {"$ne": "baseball"}},
        {"$push": { tags : "baseball" } } );

Checking the Outcome of an Update Request

As described above, a non-upsert update may or may not modify an existing object. An upsert will either modify an existing object or insert a new object. The client may determine if its most recent message on a connection updated an existing object by subsequently issuing a getlasterror command ( findOne( {getlasterror:1} ) ). If the result of the getlasterror command contains an updatedExisting field, the last message on the connection was an update request. If the updatedExisting field's value is true, that update request caused an existing object to be updated; if updatedExisting is false, no existing object was updated.

A Note About Padding

When you update an object in MongoDB, the update occurs in-place if the object has not grown in size. This is good for insert performance if the collection has many indexes.

Mongo also adaptively learns if objects in a collection tend to grow, and if they do, it adds some padding to prevent excessive movements.

See Also


Labels

$ $ Delete
operators operators Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

Comments (17)

IF YOU HAVE A QUESTION, POST IT TO THE USER GROUP.

These pages are fine for comments, but for questions, your best bet will always be the MongoDB User Group.

 
  1. Aug 17

    Anonymous says:

    test showing usage of push, pushAll, pull, and pullAll using mongo-ruby-driver ...

    test showing usage of push, pushAll, pull, and pullAll using mongo-ruby-driver

    http://gist.github.com/169258

    • Jon Hancock
  2. Nov 12

    Anonymous says:

    How do I remove a single item? For instance if I have the object {foo: {ba...

    How do I remove a single item? For instance if I have the object

    {foo: {bar: {baz: 'hello}}}
    

    and I wanted to remove bar (including it's embedded document). It would be nice to have a way to do this in an update statement.

    1. Nov 12

      Kristina Chodorow says:

      You can't, yet, but $unset is coming in 1.1.4 (see http://jira.mongodb.org/brows...

      You can't, yet, but $unset is coming in 1.1.4 (see http://jira.mongodb.org/browse/SERVER-134)

  3. Nov 18

    Anonymous says:

    Is there a way to support uniquness (or order) on list elements. I.e. when using...

    Is there a way to support uniquness (or order) on list elements.
    I.e. when using $push, you can add duplicate elements like:

    > db.c.findOne()
    {"_id" :  ObjectId( "4b040ab17b5a103277c14568")  , "arr" : [] , "name" : "a"}
    > db.c.update({name:'a'}, {$push: {arr: 1}})
    > db.c.findOne()
    {"_id" :  ObjectId( "4b040ab17b5a103277c14568")  , "name" : "a" , "arr" : [1]}
    > db.c.update({name:'a'}, {$push: {arr: 1}})
    > db.c.findOne()
    {"_id" :  ObjectId( "4b040ab17b5a103277c14568")  , "name" : "a" , "arr" : [1,1]}
    

    ... but what if I need to maintain a set of unique elements?

    For example, let's say I want to keep a list of all books owned by a person:

    {"_id": ObjectId("..."), "name": "John", "books": set(["The Adventures of Tom Sawyer", "Javascript Bible"])}
    

    I'd like a way to add a book to the set and check for existence. Is this possible with MongoDB?

    1. Nov 20

      Kristina Chodorow says:

      See http://jira.mongodb.org/browse/SERVER-176.
    2. Dec 05

      Anonymous says:

      see "$push a Unique Value" above. Gregg Lind, happy mongo user

      see "$push a Unique Value" above.

      Gregg Lind, happy mongo user

  4. Nov 27

    Anonymous says:

    Is it possible to use $pull to remove an object in an array? For example if ther...

    Is it possible to use $pull to remove an object in an array? For example if there was an object like:

    {_id:1, props: [ {name:"n1",val:"v1"}, {name:"n2", val:"v2} ]}
    

    is there a way to pull from the props array?

  5. Dec 05

    Anonymous says:

    It took my some time before I understood that update only updates the first reco...

    It took my some time before I understood that update only updates the first record it finds.

    I tried stuff like:

    db.mynames.update({_id:{$gte:0}},{$inc:{age:}});

    I just assumed that it would update all records.

    1. Dec 14

      Dwight Merriman says:

      multi update is now an option

      multi update is now an option

  6. Dec 05

    Anonymous says:

    I mean db.mynames.update({_id : {$gte:0}},{$inc:{age:1}});

    I mean

    db.mynames.update({_id : {$gte:0}},{$inc:{age:1}});

  7. Dec 21

    Anonymous says:

    Let's say I have the following object: {_id:1, elements: [ {name:n1,val:v1}, {n...

    Let's say I have the following object:

    {_id:1, elements: [ {name:n1,val:v1}, {name:n2,val:v2} ]}

    I want to remove items under "elements" whose name matches a specified value. Can this be done with $pull?

    For example, I want to remove items whose name = n1 such that after removing, the object above become:

    {_id:1, elements: [ {name:n2,val:v2} ]}

    Is this possible?

    1. Dec 22

      Eliot Horowitz says:

      in 1.3.x it is: db.foo.update ( {} , { $pull : [ { name : n1 } ] } , false , tr...

      in 1.3.x it is:
      db.foo.update

      ( {} , { $pull : [ { name : n1 } ] } , false , true )
    2. Jan 05

      Anonymous says:

      Try this: (I use 1.3 dont know if 1.2 works) db.x.y.update( {_id:1}, { $pull:...

      Try this: (I use 1.3 dont know if 1.2 works)

      db.x.y.update( {_id:1}, { $pull:{elements:{name:n1} } } )
      
  8. Jan 06

    Anonymous says:

    Let's say I have this: {_id:1, foo: { anotherfoo: 100 } } I want to increment ...

    Let's say I have this:

    {_id:1, foo: { anotherfoo: 100 } }

    I want to increment the field anotherfoo using $inc

    I'm doing this in Java but this code does not work

    coll.update(new BasicDBObject("_id", new ObjectId(id)), new BasicDBObject("$inc", new BasicDBObject("foo",new BasicDBObject("anotherfoo", 100)));

    is there a way to do this?

    thanks!

    1. Dec 31

      Anonymous says:

      sorry: i reply in the correct way Let's say I have this: {_id:1, foo: {anoth...

      sorry: i reply in the correct way

      Let's say I have this:

      {_id:1, foo: {anotherfoo: 100} }
      

      I want to increment the field anotherfoo using $inc

      I'm doing this in Java but this code does not work

      coll.update(new BasicDBObject("_id", new ObjectId(id)), new BasicDBObject("$inc", new BasicDBObject("foo",new BasicDBObject("anotherfoo", 100)));
      

      is there a way to do this?

      thanks!

      1. Dec 31

        Anonymous says:

        answering to myself, ftw coll.update(new BasicDBObject("_id", id)), new Bas...

        answering to myself, ftw

        coll.update(new BasicDBObject("_id", id)), new BasicDBObject("$inc", new BasicDBObject("foo.anotherfoo", 100)));
        
  9. Jan 18

    Anonymous says:

    I'm trying to update a subObject; { _id:1, comments:[{_id:A1,foo:bar},{_id:...

    I'm trying to update a subObject;

    { _id:1, comments:[{_id:A1,foo:bar},{_id:A2,foo:duh}] }

    I want to update {_id:A2,foo:duh} to {_id:A2,foo:blah}.

    collection.update(new BasicDBObject("comments._id", A2)),new BasicDBObject("$set", new BasicDBObject("foo", "blah")));

    does not throw an error, but does not update either.

Add Comment