Mongo.db

Basic commands

First install Mongodb, there are lots of ways to do this. I used Homebrew but I know some people suggest against it.

To get your mongo server (daemon) running, run:

mongod

To shutdown the service, run:

db.shutdownServer()

To connect to Mongo, open up a terminal and connect to the db by running:

mongo

Running mongo --help shows you all the different parameters you can use. For example, using a particular db you can run mongo mydbname. The default port is 27018 so you can change that by mongo --port 7000.

Now that you are in you may want to know what databases you have, so very similar to a lot of RDMS out there you can run show databases and use database:

show databases;
use chefs;

Mongo has collections for data, so you can run show collections. show tables also works the same.

Inserting a record

Having something in the database is a good start.

db.collection.insert({ name: "bob" });

or in version 3.2:

db.collection.insertOne({ name: "bob" });

Inserting multiple records

The insertMany method allows us to pass in an array of objects to be inserted. It inserts records linearly.

db.collection.insertMany([
  { name: "bob" },
  { name: "jim" },
  { name: "mary" }
]);

One thing to note about the above is that if any of the objects cause an error, the records after will not be inserted. You can add a second param specifying the order to be false. In this way anything that doesn't cause an error will be inserted.

db.collection.insertMany([
  { name: "bob" },
  { name: "jim" },
  { name: "mary" }
], { ordered: false });

Running Queries

To query collections using find, you can either specify an empty object which will return all records:

db.chefs.find().pretty();

You can specify attributes to search on (multiple attributes act like AND):

db.chefs.find({"style": "sioux" });

You can also count the number of records by using count.

db.chefs.find().count(); //returns a number e.g. 8

You can also chain commands such as limit to restrict the number of results (the pretty function converts the result into a human readable form):

db.records.find({ published : true }).limit(5).pretty();

Finding records based on some child object attribute is easy too:

db.chefs.find({"skills.cuisine": "French" });

Searching in Arrays is also easy. The below would match a user if their restaurant is only Bob's Kitchen:

db.chefs.find({"restaurants": ["Bob's Kitchen"] });

This would not match:

db.chefs.find({"restaurants": ["Bob's Kitchen", "Kim's Bistro"] });

But this would:

db.chefs.find({"restaurants": "Bob's Kitchen" });

Another caveat is that using brackets for arrays is an exact comparison. If the document had ["Kim's Bistro", "Bob's Kitchen"] the query below would not return any results:

db.chefs.find({"restaurants": ["Bob's Kitchen", "Kim's Bistro"] });

Just like the dot notation on an object, we can also target elements in the array using their index:

db.chefs.find({"restaurants.0": "Bob's Kitchen" });

Mongo _id

You'll notice from running any of the above that a _id is created for each record. If you don't specify a _id Mongo will create one for you.

Mongo stores record primary keys ("_id") in the BSON format. The primary key type is ObjectId, that is either generated by the application driver or by the mongod service.

In the event the driver fails to provide a _id field with a unique ObjectId, the mongod service will add it automatically using:

  • A 4-byte value representing the seconds since the Unix epoch
  • A 3-byte machine identifier (MAC Address)
  • A 2-byte process ID
  • A 3-byte counter, starting with a random value

Cursors

The point of a cursor is not to load in all the contents of a query, as in using the toArray function. The cursor sets up the query, waiting for functions to be run against it, such as the forEach function. The forEach looks very much like the forEach in Functional Reactive programming, and it acts very much the same - it streams results.

Since the Mongo shell is a Javascript interpreter you can use it for things such as cursors. If we don't assign the value returned from find then you get a cursor which iterate through records up to 20 times, triggered by typing "it".

let c = db.collection.find();
c.hasNext(); //true or false
c.next(); //displays next records
c.objsLeftInBatch(); //displays number of records left

Projection

Projection is just like the real world projection: you can let through only the things that you want. By default, when querying Mongo it returns all fields in results. If you only need certain fields then run the results through a projection, which is specified by the second param of the find method. In this param you specify fields to explicitly include or exclude by passing the attribute and a boolean 1 or 0 whether to include or not.

db.chefs.find({"restaurants.0": "Bob's Kitchen" }, {name: 1});

Query Operators

There are many query operators: Comparison operators, Element operators, Logical operators, Regex operators, Array operators.

Updating a record

db.collection.update( { name: "bob" }, { $set: { "skills.cuisine": "Spanish" } });

You can also update a document using updateOne which updates the first record matching the criteria specified.

Upserting

"Upserting" is a term meaning a record is inserted if an update attempt is performed on a record that doesn't exist.

db.collection.update( { name: "bob" }, { $set: { "skills.cuisine": "Spanish" } }, { upsert: true});

Deleting a database

use temp;
db.dropDatabase();

Deleting a collection

db.collection.drop();

Deleting a record

db.collection.remove({ attribute: value }, 1);

Deleting all records

db.collection.remove({})

Deleting multiple records

db.collection.remove( { _id : { $in: [
    ObjectId("576dbca0f48a891f0048c3ff"), 
    ObjectId("576dbca0f48a891f0048c401"), 
    ObjectId("576dbca0f48a891f0048c402"),
    ObjectId("576dbca0f48a891f0048c403"),
    ObjectId("576dbca0f48a891f0048c404"),
    ObjectId("576dbca0f48a891f0048c405")
] } } );

Renaming fields

db.mycollection.update({}, { $rename: {
  "nmae": "name",
  "pstcode": "postcode"
} }, false, true);

Indexes

Searching a non-indexed collection is O(n), so very slow when there are lots of documents. Creating an index means you are sorting that key so a search becomes O(log2n) as it uses a binary search (btree).

Creating an index is as easy as:

db.collection.createIndex({ myField: 1 });

The 1 means it is sorted ascending.

To find out what indexes already exist do:

db.collection.getIndexes();

To delete an index we use dropIndex with the same signature it was created with:

db.collection.dropIndex({ myField: 1 });

The _id is indexed by default.

Importing JSON files

mongoimport -d mydatabasename -c mycollection --drop  --jsonArray --file myJSONFile.json

Exporting Collections

It is easy to export a collection to a JSON file:

mongoexport --host my.mongo.db.host --port 37017 -d mydatabasename -c mycollection --out /wherever/whatever.json

And to export a CSV file, naming their fields:

mongoexport --db mydb --collection chefs --type=csv -f "Name","Age","DOB","Cuisine" --out chefs.csv

Flags are:

  • -d: database
  • -c: collection
  • -f: field list (to export)
  • --out:file/directory path and file to export to

Exporting is fine when you are using JSON files or importing csv files. But this is not great for backing up or restoring your databases. Instead you want to take a great big dump.

Mongodump and Mogorestore

These both export and imort BSON respectively, including any meta data and indexes you have set up.

To dump "mydatabase" run:

mongodump -d mydatabase

This creates a dump folder in your current directory containing the BSON files.

To restore you just need to specify the dump folder from the previous step:

mongorestore yourDumpFolder

You can specify any host and port numbers too, along with user name and password if you are restoring a remote server.

Aggregation operations

Check out the Mongo aggregation quick reference for Mongo piplelines.

  • match
  • project
  • sort
  • skip
  • limit

Resources