db //Tells you the current database
show collections //Shows the collections available in the current db
db.foo.save({_id:1, x:10}) //Save the document into the foo collection
db.bar.save({_id:1, x:10}) //Save the document into the bar collection
You can view the data using:
db.foo.find() //Normal
db.foo.find.pretty() //Formats the data to make it more viewable
db.foo.count() //Shows the number of documents in the collection
Mongo will automatically create a system.indexes
collection with an index entry for both collections for the _id field.
The _id field can be a number of different types. For example maybe some data is better indexed as a date like log entries etc.
db.foo.save({ _id: 1 })
db.foo.save({ _id: 3.14 })
db.foo.save({ _id: "Hello" })
db.foo.save({ _id: ISODate() })
db.foo.save({ _id: { a:'X', b:2 } })
db.foo.find()
{ "_id" : 1 }
{ "_id" : 2, "value" : "replication is cool" }
{ "_id" : 3.14 }
{ "_id" : "Hello" }
{ "_id" : ISODate("2013-09-29T11:29:06.038Z") }
{ "_id" : { "a" : "X", "b" : 2 } }
The only data type which cannot be used as an _id is an array. You can of course convert the array into a byte structure and use that instead.
If no _id is specified mongo will assign an ObjectId as the _id. You can see this using:
db.Users.save({name: 'John'})
db.Users.find()
{ "_id" : ObjectId("5248106f6538d4e1cf6daefd"), "name" : "John" }
The ObjectId is an amalgamation of a timestamp and an incrementing index. You can generate a new ObjectId using:
ObjectId()
ObjectId("524811b8d6f4a7be80e3b029")
ObjectId().getTimestamp()
ISODate("2013-09-29T11:41:18Z")
In the example above, we can access the timestamp using:
db.Users.findOne({name: 'John'})._id.getTimestamp()
The ObjectId has the advantage of being sequential and therefore it is faster for writing as each record is just appended on to the end of the file. However, if you need
It is possible to save two documents with the same _id.
db.foo.save({_id:1, x:10}) db.foo.save({_id:1, name: "John"})
In this case the last entry is what is stored. So the record at _id: 1 will be pointing to {_id:1, name: "John"}. No error occurs when the second save is done.
There is another option, the update. In this case when the second entry is done it will report and error.
db.a.insert({_id:1, x:10}) db.a.insert({_id:1, name: "John"}) E11000 duplicate key error index: test.foo.$id dup key: { : 1.0 }
The db.update allows for a sequential update of record data.
db.foo.update(query, update, options);
The options parameter is optional. Options include update one, update many or Upsert (ie update if it exists, insert if it doesn't).
db.a.save({_id:1, x:10})
db.a.update({_id:1},{$inc:{x:1}})
db.a.find()
{ "_id" : 1, "x" : 11}
db.b.save({_id:1, x:10})
db.b.update({_id:1},{$set:{y:9}})
db.b.update({_id:1},{$unset:{y: ''}})
In this case the y value is arbitrary.
To remove the field from all fields you would use:
db.b.update({},{$unset:{y: ''}}, {multi: true})
In this case the options {multi: 1}
tells mongo to apply it to multiple documents. The selector of {}
tells it to select to all documents. You could tell it to only update certain documents based on a selection:
db.a.update({x: {$lt: 11}},{$unset:{y: ''}}, {multi: true})
This removes the field where the value of x is less than 11 for all documents that meet the criteria.
db.b.save({_id:1, naem: 'John'})
db.b.find()
{ "_id" : 1, "naem" : "bob" }
db.b.update({_id:1},{$rename:{ 'naem': 'name' }})
db.a.save({_id:1})
db.a.find()
{ "_id" : 1 }
db.a.update({_id:1}, {$push: {things: 'one' }})
db.a.find()
{ "_id" : 1, "things" : [ "one" ] }
db.a.update({_id:1}, {$push: {things: 'two' }})
A set is the same as an array but it cannot contain duplicates.
db.a.update({_id:1}, {$addToSet: {things: 'two' }})
db.a.update({_id:1}, {$pull: {things: 'two' }})
db.a.update({_id:1}, {$pop: {things: 1 }})
The 1 in this case refers to the item 1 from the end.
db.a.update({_id:1}, {$pop: {things: -1 }})
The -1 in this case refers to the item 1 from the start.
The default when doing an update is to only update one record. Therefore if you have 4 records like this:
db.a.find()
{ "_id" : 1, "things" : [ 1, 2, 3 ]}
{ "_id" : 2, "things" : [ 2, 3 ]}
{ "_id" : 3, "things" : [ 3 ]}
{ "_id" : 4, "things" : [ 1, 3 ]}
And we do an update:
db.a.update({}, {$push: {things: 4}});
Instead of adding to all the records like you would expect it gives us:
db.a.find()
{ "_id" : 1, "things" : [ 1, 2, 3, 4 ]}
{ "_id" : 2, "things" : [ 2, 3 ]}
{ "_id" : 3, "things" : [ 3 ]}
{ "_id" : 4, "things" : [ 1, 3 ]}
So, it only add to record 1. To update multiple rows you need to set {multi:true}.
db.a.update({}, {$push: {things: 4}}, {multi:true});
db.a.find()
{ "_id" : 1, "things" : [ 1, 2, 3, 4, 4 ]}
{ "_id" : 2, "things" : [ 2, 3, 4 ]}
{ "_id" : 3, "things" : [ 3, 4 ]}
{ "_id" : 4, "things" : [ 1, 3, 4 ]}
If you want to update records which contain 2 you can do it with the following query:
db.a.update({things:2}, {$push: {things: 42}}, {multi:true});
db.a.find()
{ "_id" : 1, "things" : [ 1, 2, 3, 4, 4, 42 ]}
{ "_id" : 2, "things" : [ 2, 3, 4, 42 ]}
{ "_id" : 3, "things" : [ 3, 4 ]}
{ "_id" : 4, "things" : [ 1, 3, 4 ]}
Find and Modify will find and update one document which matches the query. Typically the query is something like {_id: 10}
.
db.foo.findAndModify({
query: <document>,
update: <document>,
upsert: <document>,
remove: <boolean>,
new: <boolean>,
sort: <document>,
fields: <document> });
By default findAndModify will return a the record before the modification unless new
is set to true. Then it will return the record after the modification. You can select the fields to return rather than the whole document. If remove is set to true then it will delete the document. upsert
will tell it to create the document if it does not already exist. remove
will delete the record. fields
tells what fields you want returned from the command in case you do not want all the fields to be returned.
db.a.findAndModify({query: {x: {$gt: 18}}, update: {$inc:{x:2}}, new: true})
This will find and update only one document.
findOne
returns only one document.
findOne({_id:1})
db.foo.find(query, projection)
The query
part determines the selection criteria and the projection
refers to the field that you wish to return. Please note that there is a speed cost of returning lots of unneeded fields so you should only return the smallest set of data necessary. If you do not specify a projection
then all the fields are returned. Note that unlike findOne, find returns a cursor and does not point to the data directly. You can still carry out functions on the results of the cursor like sort, skip, limit etc.
db.a.find({_id: 1})
//_id is always unique so this will return only one document
//{ "_id" : 1, "x" : 28, "y" : 2 }
db.a.find({x: 28, y: 2})
//returns all documents where x = 28 and y =2
//{ "_id" : 1, "x" : 28, "y" : 2 }
By default mongo return all the fields in a document. You cna specify a projection if you wish to specify which fields to return. Note: it treats both true
and 1
as true
, so a projection of db.a.find({_id: 1},{x: true, y: 1})
will return both the x and y fields as well as the _id
which is always returned. You can also tell it what fields not to return, so db.a.find({_id: 1},{_id: false})
will return all the fields except the _id
field. You can only include or exclude fields, you cannot use the projection to include and exclude fields in the same projection.
You can also specify ranges:
db.a.find({_id: {$gt:1, $lt:4}}, {_id:1}
In this the query returns where the _id
is greater than 1 and less than 4. It also returns only the _id
field.
You can also use the $in
operator
db.a.find({_id: {$in: [1,3]}}, {_id:1})
This will return all documents where the _id
is in the set [1,3] (ie 1 or 3)
You can also find all those not in the set using:
db.a.find({_id: {$nin: [1,3]}}, {_id:1})
You can also use negation (normally you would just use $lt
here but it is just for example):
db.a.find({_id: {$not: {$gt:3}}}, {_id:1}
You can also find elements in an array:
db.animals.save({_id: 1, name: "cat", tags: ["cute", "land"], info: {type: 'carnivore'}})
db.animals.save({_id: 2, name: "rabbit", tags: ["cute", "land"], info: {type: 'herbivore'}})
db.animals.save({_id: 3, name: "shark", tags: ["ocean"], info: {type: 'carnivore', color: null}})
db.animals.save({_id: 4, name: "dolphin", tags: ["cute", "ocean"], info: {type: 'carnivore', color: 'grey'}})
db.animals.save({_id: 5, name: "rat", tags: ["land"], info: {type: 'omnivore'}})
To find any documents that have a tag or either 'ocean' or 'cute' use the $in
operator:
db.animals.find({tags: {$in: ['cute', 'ocean']}}, {name: 1})
{ "_id" : 1, "name" : "cat" }
{ "_id" : 2, "name" : "rabbit" }
{ "_id" : 3, "name" : "shark" }
{ "_id" : 4, "name" : "dolphin" }
To find documents that have tags of both 'cute' and 'ocean' use the $all
operator:
db.animals.find({tags: {$all: ['cute', 'ocean']}}, {name: 1})
{ "_id" : 4, "name" : "dolphin" }
To check for documents not in 'cute' or 'ocean' you can use $nin
.
db.animals.find({tags: {$nin: ['cute', 'ocean']}}, {name: 1})
{ "_id" : 5, "name" : "rat" }
You can access field in a subdocument using dot notation as follows:
db.animals.find({'info.type': 'omnivore'})
//Same as db.animals.find({info: {type: 'omnivore'}})
{ "_id" : 5, "name" : "rat", "tags" : [ "land" ], "info" : { "type" : "omnivore" } }
Note that Mongo is loosely typed so there is no problem if the particular field does not exist on the document, it is just skipped if it is not there.
A field value can be null if either it is set to the value or null
or it does not exist.
db.animals.find({'info.color': 'grey'}, {name: 1, info: 1})
{ "_id" : 4, "name" : "dolphin", "info" : { "type" : "carnivore", "color" : "grey" } }
Searching for null gives us:
db.animals.find({'info.color': null}, {name: 1, info: 1})
{ "_id" : 1, "name" : "cat", "info" : { "type" : "carnivore" } }
{ "_id" : 2, "name" : "rabbit", "info" : { "type" : "herbivore" } }
{ "_id" : 3, "name" : "shark", "info" : { "type" : "carnivore", "color" : null } }
{ "_id" : 5, "name" : "rat", "info" : { "type" : "omnivore" } }
This returns where the field is null
ie for the shark and where the field does not exist at all.
To check if field exists you can use the $exists
operator.
db.animals.find({'info.color': {$exists: true}}, {name: 1, info: 1})
{ "_id" : 3, "name" : "shark", "info" : { "type" : "carnivore", "color" : null } }
{ "_id" : 4, "name" : "dolphin", "info" : { "type" : "carnivore", "color" : "grey" } }
This returns the documents which have the field, even if the value is null. the opposite of this is:
db.animals.find({'info.color': {$exists: false}}, {name: 1, info: 1})
{ "_id" : 1, "name" : "cat", "info" : { "type" : "carnivore" } }
{ "_id" : 2, "name" : "rabbit", "info" : { "type" : "herbivore" } }
{ "_id" : 5, "name" : "rat", "info" : { "type" : "omnivore" } }
Note: the existence of a field can be a useful indicator of the version of the document. So v1 of the api has one field, v2 of the api has a different field etc.
You can sort the results (1 is ascending, -1 is descending) of a find using:
db.animals.find({}, {name: 1}).sort({name: 1})
You can also sort on multiple fields using:
db.animals.find({}, {name: 1}).sort({name: 1, 'info.type': 1})
You can limit the number of documents returned. This can be useful for paging or finding the top 10 results etc.
db.animals.find({}).limit(2)
Skip is useful for paging.
db.animals.find({}).skip(2).limit(2)