Skip to content

Instantly share code, notes, and snippets.

@leommoore
Last active January 16, 2021 16:36
Show Gist options
  • Save leommoore/6751647 to your computer and use it in GitHub Desktop.
Save leommoore/6751647 to your computer and use it in GitHub Desktop.
MongoDB - Basic Commands

#MongoDB - Basic Commands

##Saving Data

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.

###_id field types 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.

###Mongo ObjectId

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()

###Optimizing Read and Writes 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

###save v insert 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 }

##Updating Data 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}

###Adding a field to a document

db.b.save({_id:1, x:10})
db.b.update({_id:1},{$set:{y:9}})

###Removing a field from a document

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.

###Renaming a field in a document

db.b.save({_id:1, naem: 'John'})
db.b.find()
{ "_id" : 1, "naem" : "bob" }
db.b.update({_id:1},{$rename:{ 'naem': 'name' }})

###Adding a value to an array field

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' }})

###Add a value to a set field A set is the same as an array but it cannot contain duplicates.

db.a.update({_id:1}, {$addToSet: {things: 'two' }})

###Remove a value from an array

db.a.update({_id:1}, {$pull: {things: 'two' }})

###Remove the last item from an array

db.a.update({_id:1}, {$pop: {things: 1 }})

The 1 in this case refers to the item 1 from the end.

###Remove the first item from an array

db.a.update({_id:1}, {$pop: {things: -1 }})

The -1 in this case refers to the item 1 from the start.

###Updating Multiple Records 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 ]}

###Updating Multiple Records based on Criteria 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 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 findOne returns only one document.

findOne({_id:1})

###Find

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 }

####Projections (Fields) 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.

####Ranges 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}) 

####Negation

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}

####Arrays 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" }

####Dot Notation 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.

####Null fields 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.

####Check for field existence 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.

###Sorting 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})

###Limit 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 Skip is useful for paging.

db.animals.find({}).skip(2).limit(2)
@gkiranseo
Copy link

Thanks for sharing basic commands on MongoDB. Very useful information.

@radimek
Copy link

radimek commented Oct 5, 2017

Thanks for very useful notes!

@gatherheart
Copy link

Thanks for sharing your notes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment