In Chapter 1, we discussed MongoDB features and how to install MongoDB on Windows and Linux. We also discussed terms used in MongoDB and how to create a database. In this chapter, we are going to discuss how to perform create, read, update, and delete (CRUD) operations in MongoDB. This chapter also describes how to work with embedded document and arrays. We are going to discuss the following topics:
Collections.
MongoDB CRUD operations.
Bulk write operations.
MongoDB import and export.
Embedded documents.
Working with arrays.
Array of embedded documents.
Projection.
Dealing with null and missing values.
Working with limit() and skip().
Working with Node.js and MongoDB.
Collections
MongoDB collections are similar to tables in RDBMS. In MongoDB, collections are created automatically when we refer to them in a command. For an example, consider the following command.
db.person.insert({_id:100001,name:"Taanushree A S",age:10})
This command creates a collection named person if it is not present. If it is present, it simply inserts a document into the person collection.
Recipe 2-1. Create a Collection
In this recipe, we are going to discuss how to create a collection.
Problem
You want to create a collection named person using the db.createCollection() command.
Solution
Use the following syntax to create a collection.
db.createCollection (<name>)
How It Works
Let’s follow the steps in this section to create a collection named person.
Step 1: Create a Collection
To create a collection by the name person use the following command.
db.createCollection("person")
Here is the output,
> db.createCollection("person")
{ "ok" : 1 }
>
To confirm the existence of the collection, type the following command in the mongo shell.
> show collections
person
>
We can now see the collection named person.
Recipe 2-2. Create Capped Collections
In this recipe, we are going to discuss what a capped collection is and how to create one. Capped collections are fixed-size collection for which we can specify the maximum size of the collection in bytes and the number of documents allowed. Capped collections work similar to a circular buffer: Once it fills its allocated space, it makes room for new documents by overwriting the oldest documents in the collection.
There are some limitations of capped collections:
You can’t shard capped collections.
You can’t use the aggregation pipeline operator $out to write results to a capped collection.
You can’t delete documents from a capped collection.
Creating an index allows you to perform efficient update operations.
Problem
You want to create a capped collection named student using the db.createCollection() method.
Here, MongoDB retrieves the results in the order of insertion. To retrieve documents in the reverse order, use sort() and set the $natural parameter to -1 as shown here.
Notice that the first document is overwritten by the third document, as the maximum number of documents allowed in the student capped collection is two.
Create Operations
Create operations allow us to insert documents into a collection. These insert operations target a single collection. All write operations are atomic at the level of a single document.
MongoDB provides several methods for inserting documents, listed in Table 2-1.
Table 2-1
Insert Methods
db.collection.insertOne
Inserts a single document
db.collection.insertMany
Inserts multiple documents
db.collection.insert
Inserts a single document or multiple documents
Recipe 2-3. Insert Documents
In this recipe, we are going to discuss various methods to insert documents into a collection.
Problem
You want to insert documents into the collection person.
Solution
Use the following syntax to insert documents.
db.collection.insertOne()
db.collection.insertMany()
How It Works
Let’s follow the steps in this section to insert documents into the collection person.
Step 1: Insert a Single Document
To insert a single document into the collection person, use the following command.
In a compound query, you can specify conditions for more than one field. To select all documents in the person collection where the name equals "shobana" and the age is greater than 10, here is the command:
db.person.find({ name:"shobana",age:{$gt:10}})
Here is the output,
> db.person.find({ name:"shobana",age:{$gt:10}})
{ "_id" : 1004, "name" : "shobana", "age" : 44 }
>
Step 5: Specify OR Conditions
You can use $or in a compound query to join each clause with a logical or conjunction.
The operator $or selects the documents from the collection that match at least one of the selected conditions.
To select all documents in the person collection where the name equals "shobana" or age equals 20, here is the command:
Here, the modifiedCount is 2, which indicates that the preceding command modified two documents in the student collection.
Step 3: Replace a Document
You can replace the entire content of a document except the _id field by passing an entirely new document as the second argument to db.collection.replaceOne() as shown here.
Execute the following command to replace the first document from the student collection where name equals "John".
Do not include update operators in the replacement document. You can omit the _id field in the replacement document because the _id field is immutable. However, if you want to include the _id field, use the same value as the current value.
Delete Operations
Delete operations allow us to delete documents from a collection. MongoDB provides two delete methods, as shown in Table 2-3.
Table 2-3
Delete Methods
db.collection.deleteOne
To delete a single document
db.collection.updateMany
To delete multiple documents
In MongoDB, delete operations target a single collection.
Recipe 2-6. Delete Documents
In this recipe, we discuss how to delete documents.
Problem
You want to delete documents from a collection.
Solution
The following methods are used to delete documents from a collection.
db.collection.deleteOne()
db.collection.deleteMany()
How It Works
Let’s follow the steps in this section to delete documents in a collection.
Step 1: Delete Only One Document That Matches a Condition
To delete a document from the collectionstudent where name is John, use this code.
db.student.deleteOne({name: "John"})
Here is the output,
> db.student.deleteOne({name: "John"})
{ "acknowledged" : true, "deletedCount" : 1 }
>
Step 2: Delete All Documents That Match a Condition
To delete all documents from the collectionstudent where name is Jack, use this code.
db.student.deleteMany({name: "Jack"})
Here is the output,
> db.student.deleteMany({name: "Jack"})
{ "acknowledged" : true, "deletedCount" : 2 }
>
Step 3: Delete All Documents from a Collection
To delete all documents from the collection student, pass an empty filter document to the db.student.deleteMany() method.
db.student.deleteMany({})
Here is the output,
> db.student.deleteMany({})
{ "acknowledged" : true, "deletedCount" : 3 }
>
MongoDB Import and Export
The MongoDB import tool allows us to import content from JSON, comma-separated value (CSV), and tab-separated value (TSV) files. MongoDB import only supports files that are UTF-8 encoded.
The MongoDB export tool allows us to export data stored in MongoDB instances as JSON or CSV files.
Recipe 2-7. Work with Mongo Import
In this recipe, we are going to discuss how to import data from a CSV file.
Problem
You want to import data from the student.csv file to the students collection.
Solution
The following command is used to perform a Mongo import.
mongoimport
Note
To work with the Mongo import command, start the mongod process and open another command prompt to issue the mongo import command.
How It Works
Let’s follow the steps in this section to work with Mongo import.
Create a student.csv file using the following data in the C:Sample directory.
_id,name,class
1,John,II
2,James,III
3,Joshi,I
Execute the following command to import data from the student.csv file to the students collection.
mongoimport --db student --collection students --type csv --headerline --file c:Samplestudent.csv
Here, the marks field contains an embedded document.
Execute the following code to create an employee database and employee collection.
use employee
db.employee.insertMany([{_id:1001,name:"John",address:{previous:"123,1st Main",current:"234,2nd Main"},unit:"Hadoop"},{_id:1002,name:"Jack", address:{previous:"Cresent Street",current:"234,Bald Hill Street"},unit:"MongoDB"},{_id:1003,name:"James", address:{previous:"Cresent Street",current:"234,Hill Street"},unit:"Spark"}])
Recipe 2-9. Query Embedded Documents
In this recipe, we are going to discuss how to query embedded documents.
Problem
You want to query embedded documents.
Solution
The following command is used to query embedded documents.
db.collection.find()
You need to pass the filter document {<field>:<value>} to the find() method where <value> is the document to match.
How It Works
Let’s follow the steps in this section to query embedded documents.
Step 1: Match an Embedded or Nested Document
To perform an equality match on the embedded document, you need to specify the exact match document in the <value> document, including the field order.
To select all documents where the address field equals the document {previous:"Cresent Street",current:"234,Bald Hill Street"}:
db.employee.find( { address: { previous:"Cresent Street",current:"234,Bald Hill Street" }} )
To specify an equality condition on an array, you need to specify the exact array to match in the <value> of the query document {<field>:<value>}.
To select all documents where the projects value is an array with exactly two elements, "Hadoop" and "MongoDB", in the specified order, use the following commands.
To query all documents where the scores field is an array that contains at least one element whose value is greater than 26 we can use the $gt operator.
Here, one element of the scores array can satisfy the greater than 20 condition and another element can satisfy the less than 24 condition, or a single element can satisfy both the conditions.
Step 5: Using the $elemMatch operator
The $elemMatch operator allows us to specify multiple conditions on the array elements such that at least one array element should satisfy all of the specified conditions.
You can use the $addToSet operator to add a value to an array. $addToSet adds a value to an array only if a value is not present. If a value is present, it does not do anything.
To add hobbies to the employeedetails collection, use this code.
Equality matching on the array of an embedded document requires an exact match of the specified document, including field order.
Step 2: Query for a Field Embedded in an Array of Documents
You can use dot notation to query a field embedded in an array of documents. The following command selects all documents in the marks array where at least one embedded document contains the field total that has a value that is less than 400.
Step 3: Array Index to Query for a Field in the Embedded Document
The command shown here selects all the documents in the marks array where the first element of the document contains the field class, which has a value that is equal to "II".
The query shown here returns the documents that only contain the name field with a value of null. In BSON, set the null value to 10.
db.sample.find( { name: { $type: 10 } } )
Here is the output,
> db.sample.find( { name: { $type: 10 } } )
{ "_id" : 1, "name" : null }
>
Step 3: Existence Check
You can use the $exist operator to check for the existence of a field.
The following query returns the documents that do not contain the name field.
db.sample.find( { name: { $exists: false } } )
Here is the output,
> db.sample.find( { name: { $exists: false } } )
{ "_id" : 2 }
>
Iterate a Cursor
The db.collection.find() method of MongoDB returns a cursor. You need to iterate a cursor to access the documents. You can manually iterate a cursor in the mongo shell by assigning a cursor returned from the find() method to a variable using the var keyword.
If you are not assigning a cursor to a variable using the var keyword, it is automatically iterated up to 20 times to print the first 20 documents.
Recipe 2-14. Iterate a Cursor
In this recipe, we are going to discuss how to iterate a cursor in the mongo shell.
Problem
You want to iterate a cursor in the mongo shell.
Solution
The following syntax is used to iterate a cursor.
var myCursor = db.collection.find()
myCursor
How It Works
Let’s follow the steps in this section to iterate a cursor. First, create a numbers collection.
db.numbers.insert({_id:1,number:1});
db.numbers.insert({_id:2,number:2});
db.numbers.insert({_id:3,number:3});
db.numbers.insert({_id:4,number:4});
db.numbers.insert({_id:5,number:5});
db.numbers.insert({_id:6,number:6});
db.numbers.insert({_id:7,number:7});
db.numbers.insert({_id:8,number:8});
db.numbers.insert({_id:9,number:9});
db.numbers.insert({_id:10,number:10});
db.numbers.insert({_id:11,number:11});
db.numbers.insert({_id:12,number:12});
db.numbers.insert({_id:13,number:13});
db.numbers.insert({_id:14,number:14});
db.numbers.insert({_id:15,number:15});
db.numbers.insert({_id:16,number:16});
db.numbers.insert({_id:17,number:17});
db.numbers.insert({_id:18,number:18});
db.numbers.insert({_id:19,number:19});
db.numbers.insert({_id:20,number:20});
db.numbers.insert({_id:21,number:21});
db.numbers.insert({_id:22,number:22});
db.numbers.insert({_id:23,number:23});
db.numbers.insert({_id:24,number:24});
db.numbers.insert({_id:25,number:25});
Issue the following commands to iterate a cursor.
var myCursor = db.numbers.find()
myCursor
Here is the output,
> var myCursor = db.numbers.find()
> myCursor
{ "_id" : 1, "number" : 1 }
{ "_id" : 2, "number" : 2 }
{ "_id" : 3, "number" : 3 }
{ "_id" : 4, "number" : 4 }
{ "_id" : 5, "number" : 5 }
{ "_id" : 6, "number" : 6 }
{ "_id" : 7, "number" : 7 }
{ "_id" : 8, "number" : 8 }
{ "_id" : 9, "number" : 9 }
{ "_id" : 10, "number" : 10 }
{ "_id" : 11, "number" : 11 }
{ "_id" : 12, "number" : 12 }
{ "_id" : 13, "number" : 13 }
{ "_id" : 14, "number" : 14 }
{ "_id" : 15, "number" : 15 }
{ "_id" : 16, "number" : 16 }
{ "_id" : 17, "number" : 17 }
{ "_id" : 18, "number" : 18 }
{ "_id" : 19, "number" : 19 }
{ "_id" : 20, "number" : 20 }
Type "it" for more
> it
{ "_id" : 21, "number" : 21 }
{ "_id" : 22, "number" : 22 }
{ "_id" : 23, "number" : 23 }
{ "_id" : 24, "number" : 24 }
{ "_id" : 25, "number" : 25 }
>
You can also use the cursor method next() to access the document.
var myCursor=db.numbers.find({});
while(myCursor.hasNext()){
print(tojson(myCursor.next()));
}
Here is the output,
> var myCursor=db.numbers.find({});
> while(myCursor.hasNext()){
... print(tojson(myCursor.next()));
... }
{ "_id" : 1, "number" : 1 }
{ "_id" : 2, "number" : 2 }
{ "_id" : 3, "number" : 3 }
{ "_id" : 4, "number" : 4 }
{ "_id" : 5, "number" : 5 }
{ "_id" : 6, "number" : 6 }
{ "_id" : 7, "number" : 7 }
{ "_id" : 8, "number" : 8 }
{ "_id" : 9, "number" : 9 }
{ "_id" : 10, "number" : 10 }
{ "_id" : 11, "number" : 11 }
{ "_id" : 12, "number" : 12 }
{ "_id" : 13, "number" : 13 }
{ "_id" : 14, "number" : 14 }
{ "_id" : 15, "number" : 15 }
{ "_id" : 16, "number" : 16 }
{ "_id" : 17, "number" : 17 }
{ "_id" : 18, "number" : 18 }
{ "_id" : 19, "number" : 19 }
{ "_id" : 20, "number" : 20 }
{ "_id" : 21, "number" : 21 }
{ "_id" : 22, "number" : 22 }
{ "_id" : 23, "number" : 23 }
{ "_id" : 24, "number" : 24 }
{ "_id" : 25, "number" : 25 }
>
You can also use forEach to iterate the cursor and access the document.
var myCursor = db.numbers.find()
myCursor.forEach(printjson);
> var myCursor = db.numbers.find()
> myCursor.forEach(printjson);
{ "_id" : 1, "number" : 1 }
{ "_id" : 2, "number" : 2 }
{ "_id" : 3, "number" : 3 }
{ "_id" : 4, "number" : 4 }
{ "_id" : 5, "number" : 5 }
{ "_id" : 6, "number" : 6 }
{ "_id" : 7, "number" : 7 }
{ "_id" : 8, "number" : 8 }
{ "_id" : 9, "number" : 9 }
{ "_id" : 10, "number" : 10 }
{ "_id" : 11, "number" : 11 }
{ "_id" : 12, "number" : 12 }
{ "_id" : 13, "number" : 13 }
{ "_id" : 14, "number" : 14 }
{ "_id" : 15, "number" : 15 }
{ "_id" : 16, "number" : 16 }
{ "_id" : 17, "number" : 17 }
{ "_id" : 18, "number" : 18 }
{ "_id" : 19, "number" : 19 }
{ "_id" : 20, "number" : 20 }
{ "_id" : 21, "number" : 21 }
{ "_id" : 22, "number" : 22 }
{ "_id" : 23, "number" : 23 }
{ "_id" : 24, "number" : 24 }
{ "_id" : 25, "number" : 25 }
>
Working with the limit() and skip() Methods
The limit() method is used to limit the number of documents in the query results and the skip() method skips the given number of documents in the query result.
Recipe 2-15. limit() and skip() Methods
In this recipe, we are going to discuss how to work with the limit() and skip() methods.
Problem
You want to limit and skip the documents in a collection.
Solution
The following syntax is used to limit the number of documents in the query result.
db.collection.find().limit(2)
The following syntax is used to skip a given number of documents in the query result.
db.collection.find().skip(2)
How It Works
Let’s follow the steps in this section to work with the limit() and skip() methods. Consider the numbers collection created in Recipe 2-14.
To display the first two documents, use this code.
db.numbers.find().limit(2)
Here is the output,
> db.numbers.find().limit(2)
{ "_id" : 1, "number" : 1 }
{ "_id" : 2, "number" : 2 }
>
To skip the first five documents, use this code.
db.numbers.find().skip(5)
Here is the output,
> db.numbers.find().skip(5)
{ "_id" : 6, "number" : 6 }
{ "_id" : 7, "number" : 7 }
{ "_id" : 8, "number" : 8 }
{ "_id" : 9, "number" : 9 }
{ "_id" : 10, "number" : 10 }
{ "_id" : 11, "number" : 11 }
{ "_id" : 12, "number" : 12 }
{ "_id" : 13, "number" : 13 }
{ "_id" : 14, "number" : 14 }
{ "_id" : 15, "number" : 15 }
{ "_id" : 16, "number" : 16 }
{ "_id" : 17, "number" : 17 }
{ "_id" : 18, "number" : 18 }
{ "_id" : 19, "number" : 19 }
{ "_id" : 20, "number" : 20 }
{ "_id" : 21, "number" : 21 }
{ "_id" : 22, "number" : 22 }
{ "_id" : 23, "number" : 23 }
{ "_id" : 24, "number" : 24 }
{ "_id" : 25, "number" : 25 }
>
Working with Node.js and MongoDB
MongoDB is one of the most popular databases used with Node.js.
Recipe 2-16. Node.js and MongoDB
In this recipe, we are going to discuss how to work with Node.js and MongoDB.
Problem
You want to perform CRUD operations using Node.js.