CRUD operations in MongoDB

CRUD

courtesy

In this post, we’re going to see a few example of CRUD operation in MongoDB

Restoring using mongorestore

After making sure that mongod and mongo are running, go to the dump’s parent directory in a new terminal. And use the command mongorestore dump. Where dump is the folder name in which the database dump is present.

Restoring using mongorestore

Creating Documents

There’re two principal commands for creating documents in MongoDB:

  • insertOne()
  • insertMany()

There’re other ways as well such as Update commands. We call these operations, upserts. Upserts occurs when there’re no documents that match the selector used to identify documents.

Although MongoDB inserts ID by it’s own, We can manually insert custom IDs as well by specifying _id parameter in the insert...() functions.

To insert multiple documents we can use insertMany() - which takes an array of documents as parameter. When executed, it returns multiple ids for each document in the array. To drop the collection, use drop() command. Sometimes, when doing bulk inserts - we may insert duplicate values. Specifically, if we try to insert duplicate _ids, we’ll get the duplicate key error:



db.startup.insertMany(
  [
  {_id:"id1", name:"Uber"},
  {_id:"id2", name:"Airbnb"},
  {_id:"id1", name:"Uber"},
  ]
  );

MongoDB duplicate key error

MongoDB stops inserting operation, if it encounters an error, to supress that - we can supply ordered:false parameter. Ex:



db.startup.insertMany(
[
{_id:"id1", name:"Uber"},
{_id:"id2", name:"Airbnb"},
{_id:"id1", name:"Airbnb"},
],
{ordered: false}
);

The _id field

MongoDB assigns an _id field to each document and assigns primary index on it. There’re ways by which we can apply secondary indices as well. By default, MongoDB creates values for the _id field of type ObjectID. This value is defined in BSON spec and it’s structured this way:

ObjectID (12 bytes HEX string) = Date (4 bytes, a timestamp value representing number of seconds since the Unix epoch) + MAC address (3 bytes) + PID (2 bytes) + Counter (3 bytes)

Reading documents

To apply specific value filters, we can pass specific values to the find() command. Here is a SQL query:

SELECT * FROM Table1 WHERE name = 'ABC'

which is equivalent to the following in MongoDB (notice Collection1 for Table1):

db.Collection1.find({name: 'ABC'})

We can chain count() to get the number of results, pretty() to get a readable result. The results can be further narrowed by adding additional parameters:

db.Collection1.find({name: 'ABC', rollNo: 5})

It’s important to notice that these filters are ANDed together, by default. To apply an OR filter, we need to use $or. These filters will be specified depending upon the structure of the document. Ex: for object attribute name for an object school, we need to specify filter like "school.name" = 'AUHS'

We’re using here the DOT notation, by trying to access a nested field name of a field school. Also notice that the filters are quoted, without which we’ll get syntax errors.

Equality matches on arrays can be performed:

  • on the entire arrays
  • based on any element
  • based on a specific element
  • more complex matches using operators

In the below query:

db.Collection1.find({name: ['ABC','XYZ']})

MongoDB is going to identify documents by an exact match to an array of one or more values. Now for these types of queries, the order of elements matters, meaning that we will only match documents that have ABC followed by XYZ and those are the only 2 elements of the array name


{name:["ABC","GHI","XYZ"]},
{name:["DEF","ABC","XYZ"]}

In the above document, let’s say that we need to get all the documnts where ABC is the first element. So, we’ll use the below filter:

db.Schools.find({'name.0': 'ABC' })

Cursors in MongoDB

MongoDB returns results in batches. To see how many objects are left in a batch, we use objLeftInBatch() like this:


var c = db.Schools.find();
var doc = function() {return c.hasNext()? c.next : null;}
c.objLeftInBatch();

To iterate through this batch we can use doc() that we setup in the above code block. More learning on cursors can be found at https://docs.mongodb.com/

Projection in MongoDB

Projection is a handy way of reducing the size of the data returned for any one query. By default MongoDB returns all fields in all documents for queries. To limit the amount of data that MongoDB sends to the application, we can include projections in the queries to reduce network overhead and processing requirements by limiting the fields that’re returned in results documents. They’re provided as second argument to the find() command. Now, if we need to limit our documents so that they just contain a title. We can do that using this db.Schools.find({name:"ABC"},{rollNo:1}). In the result, _id is always returned. To exclude it, use db.Schools.find({name: "ABC"},{rollNo: 1, _id: 0}).. So, to exclude any field, use 0 next to the colon in project query.

Comparison operators in MongoDB

We can use comparison operators as well in our queries. Eg: Use db.Schools.find({rollNo: {$gt: 10}}) To find all students having roll number beyond than 10. Notice the $gt operator. Combine this filter with $lt for getting results beyond roll number 10 and before roll number 50: db.Schools.find({rollNo: {$gt: 10, $lt: 50}}).

There’re other operators as well: $gte (greater than, equal to), $lte (less than, equal to), $ne (not equal to). One thing to notice about the not equal to ($ne) operator is that it not only returns documents having value not equal to specified value but also returns documents not having the attribute itself.

Element operators in MongoDB

MongoDB because of it’s flexible data model supports operators that allow us to detect the presence of or absence of a given field. This flexibility in terms of data models also extends to the data type of a field value. Because it’s possible although not usually a good idea, to have the same field in a collection have a different type of value from one document to another. These operators are used for finding the existence of elements ($exists) and data type of the field using the $type operator.

Logical operators

Like SQL, there’re logical operators such as $and, $or, $not and $nor. These’re the examples:


db.Schools.find({
  $and: [{ rollNo: { $gt: 10 }}, { rollNo: { $gt: 50 }}]
  })

db.Schools.find({
  $or: [{ rollNo: { $gt: 10 }}, { rollNo: { $gt: 50 }}]
  })

Now, why there’s an $and operator when the filters are by default ANDed? Because, in a JSON document, we cannot have duplicate keys. In the above $and example, we’re ANDing rollNo twice. Remember that $and is used we need to filter data on the same field.

Regular operators

  • The slashes / in the below regex code means the start and end of the regular expression.
  • The carat ^ means start at the beginning of whatever value we’re matching against and match exactly a capital AB.
  • The dot . is the wild card character.
  • The arterisk * indicates match any character any number of times
  • \s means a space character after AB

db.Schools.find({
{ name: { $regex: /^AB\s.*/ }}
})

Array operators

These operators are used to work on arrays. For getting matching values from an array ($all), arrays of a particular size ($size) and $elemMatch - which requires all criteria be satisfied within a single element of an array field.

Updating documents

MongoDB provides 3 ways to update documents.

  • updateOne() - the first argument is the filter expression, second specifies the values to be updated
  • updateMany()
  • replaceOne()

db.Schools.updateOne({ name: "ABC" }, { $set: { rollNo: 15 } })

There are a couple of update operators. In the above query, $set operator simply replaces (or adds if not already exists) the value for the field being specified. There are array update operators as well. To apply updates for each array element, use the $each. $position modifies the $push operator to specify the position in the array to add elements.

Sometimes, we might see elements set to NULL. It’s better to remove them altogether using $unset operator.


db.Schools.updateMany({ name: null }, { $unset: { name: "" } })

Upserts of update command

Upserts are operations for which, if no document is found matching our filter, we insert a new document - hence the term upsert.

And here we finish second week course notes

Photos