Thursday 30 June 2016

Creating and Reading documents


In this post, we are going to see how we can Create and Read documents in MongoDB. Before going to start our tutorial make sure that you have already installed MongoDB successfully on your machine. If not, please refer my previous post.

Let's get started.

Documents in MongoDB :

MongoDB stores data as BSON(Binary JSON) documents. Below one is the sample document in MongoDB.


MongoDB document are composed of "field and value" pairs. The value may be a simple integer value, string, an array, another document etc.


fig : Document structure in MongoDB

Creating Collections:

Launch your mongod process using command prompt and connect to test database.

First, let's see how to create a collection in MongoDB. To create a collection in MongoDB, one should use "createCollection" command.

Note : commands in MongoDB uses CamelCase notation.


To list all databases in MongoDB, we can use "show dbs" or "show databases" command.



To check the database in which you are currently working, you can use "db" command.


To use a particular database in MongoDB, you can issue "use databaseName" command. Here databaseName is your db name.


To list all collections inside your current database, you can issue "show collections". It will display all collections inside your current database.


Here foo, fun, grades, output, posts, sample, small_zips, stuff etc., all are my collections those I have created inside my current database.


Insert data into MongoDB collection :


InsertOne :

Now, let's try to insert one document into "sample" collection.

To insert one document into MongoDB collection we are using "insertOne" command.


Here "db" is a system variable, which represents the current database. "sample" is the collection name in which you are going to insert the document. And "insertOne" is the MongoDB command to insert one document into the collection, similarly we have "insertMany" command to insert multiple documents into a collection.

Note : You can directly issue the above insertOne command in your mongo shell even though the collections doesn't exists. MongoDB doesn't throw any error message. This is called flexible schema / Dynamic schema. It means that we don't require any schema to create the collection inside mongoDB.

As you see in the above picture, MongoDB inserted one ObjectId into your document. This ID is unique across your collection i.e. it acts as a primary key inside your collection. An unique primary index will be created on this field by default. It enables us to retrieve documents based on their ID very efficiently. Of course, we can also create secondary indexes on MongoDB and we can discuss about secondary indexes on other posts. 



All ObjectId values are 12-Byte hex strings. The first 4 bytes are a value representing the seconds in UNIX format (timestamp), the next 3 bytes represents MAC address for the machine on which the MongoDB server is running. then 2 bytes contains the processID. Finally, the last 3 bytes are counter to ensure that all ObjectIds are unique. This is how an ObjectId constructed inside your document.

We can also insert a document and provide the ID in-advance. So, let's see the example of that :


InsertMany :

If you want to insert more documents at a time into your collection, you can consider using "insertMany" command. We should pass an array of documents to insertMany command. Let's see one example for the same :



We can see what happens here is about what you would expect given our understanding of the return value from insertOne instead of a single inserted ID value, it returned array of ObjectIDs for all of the documents that were inserted. Note that for the above inserted documents we didn't specify ID field. So. mongoDB created one for each document.

If you are doing bulk insert (inserting many documents using insertOne), it is possible to get some errors or exceptions for one of the documents that you are inserting. So to deal with this type of scenario, we can couple of different options with insertMany command. You can choose either "ordered" inserts or "unordered" inserts. 

Let's see one example for this type : 

Now' I'm going to insert the below set of documents into movies collection using insertMany command. You can see that _id field is same for "The Conjuring-2" and "Avatar". Let's see what happens when we try to insert these documents.

db.movies.insertMany([
{name:"The cojuring-2",year:2016,_id:"rrtavhsf"},
{name:"Titanic",year:1999,_id:"resfhy"},
{name:"Avatar",year:"2010",_id:"rrtavhsf"},
{name:"Kick",year:2009,_id:"hehehe25"}
])

Before going to insert the data, let's drop the collection by using below command to make sure that the collection didn't exists already.


Great !!, the collection has been dropped. Now let's insert the data into movies collection.


So, this is what I wanted to show you. Note that MongoDB inserted only 2 documents into the collections and thrown an error saying that "duplicate key error collection". By default insertMany does an ordered insert, meaning that as soon as it encounters an error, it will stop inserting documents. In this case what happened was, we inserted first document ("The Cojuring-2"), no problem. Then inserted second document ("Titanic"), no problem. But, when MongoDB got the third document, because the _id field exactly same as the _id of the first document. As we know that _id must be unique across your collection, this caused an error, meaning that this command just bailed out. This means that only 2 documents were inserted out of 4. In many applications we might simply want our application to keep going if it encounters an error because either we're fine with the documents that erred out not being inserted or we have a separate process to dealing with these type of documents.

Now, let's see the same insertMany command with "ordered" option. Make sure that you have dropped your collection before going to run insertMany command.



db.movies.insertMany([
{name:"The cojuring-2",year:2016,_id:"rrtavhsf"},
{name:"Titanic",year:1999,_id:"resfhy"},
{name:"Avatar",year:"2010",_id:"rrtavhsf"},
{name:"Kick",year:2009,_id:"hehehe25"}],
{ordered:false})



See, this time MongoDB inserted 3 documents. In this case we used un-ordered  insert, meaning that if it encounters an error, it will still try to insert rest of the documents.

So, creating MongoDB documents we have so far looked at "insert" and "insertMany" commands. These are the 2 main command in MongoDB to create documents. Other than these 2, with the help of "update" command also we can create documents. We called these operations "upserts". It occurs when no documents match the selector used to identify documents that should be updated. We will discuss about "upserts" later in this post.

Reading Documents :


Let's move on to reading documents in MongoDB. We can run java commands on MongoDB. Now, let's try to insert 100 documents using below for loop.

for(i=1;i<=100;i++) db.sample.insertOne({a:i})


If you want to check how many are there inside "sample" collection, you can issue below command in Mongo shell.


Okay, now let's try to get the data back from MongoDB using "find" command. Let's quickly show the structure of "find" command in MongoDB.


As we know that "db" is a system variable which database you have connected to. "sample" is the collection name. "find" is a MongoDB command which is used to retrieve the data from a collection. Inside the command, the first JSON "{a:100}" is the query criteria (similar to WHERE clause in SQL world). {a:100} means that it retrieve the document from "sample" collection where a:100. The second JSON "{_id:0,a:1}" is the Projection criteria i.e. if you want to select/print only particular fields from the collection you can use projection JSON. In this case we suppressed "_id" filed and selected only field "a". And the last one is the cursor modifier. find() method always returns a cursor to the returning documents. To access remaining documents, you need to iterate the cursor.


If the returned cursor is not assigned to a variable using the "var" keyword, then the cursor automatically iterates 20 times.


Just type "it" to get the next 20 documents.



For example, if you mention the query like below.


then, MongoDB takes the last value only. In this case even though we have given 3 values for the field "a", MongoDB ignores first 2 values and considered only the lase value.

If you want to get the data in more readable fashion you can "pretty" command after find.


Similarly, if you want to quickly know the structure of the collection, you can consider using findOne() command.


By default, findOne() comes with pretty function.



Logical AND with find :

Below query perform logical AND operation.


It means that both both the values should be TRUE, then only MongoDB returns matched documents.

Find on embedded document :

In simple words, the document inside another document is called "Embedded document". Below is the example for how we can embed one document in another document inside MongoDB.


Here, you can see that the "Address" field is having another document which is called as Embedded document. Let's try to insert one embedded document using below query.


 If you want get the documents based on "City", then you have to issue the below command.


Here, we're using dot (.) operator to access the fields of embedded document.

Note : You no need to use double quotes (""), you use single quotes also(' '), both work fine.


Equality matches on Arrays :

Coming to the quality matches on an array, we can consider :

  • On the entire array
  • based on any element
  • based on specific element
  • more complex matches using operators
Let's try to insert one simple document into "name" collection.



First, let's try to identify documents by an exact match to an array of one or more values. For these type of search, order of the elements should be same in query and the collection.

The below query doesn't return anything since the order of the elements in the query and the documents is different.


Now, let's try with the same order what ever there in the collection.


Great !!, one document has been retrieved.

Now, issue the below command in Mongo shell and see the magic.


Wow, we got one document back. The above command searches the value "James" inside the array-a. If the array has the specified value, then MongoDB returns that particular document.

Now, try the below command.



Let's look at the above command, here "a.0" means first filed inside the array. Similarly, we can access the 2nd element using "a.1". Now, let's try the below one.


Oops, it doesn't return anything back. Hope, you know the answer why it doesn't return anything.


Cursors :

As we discussed already MongoDB find method returns a cursor. Returns in Batches.

Use the below command to insert 100 sample documents into "num" collection.



Assign the returned cursor from find method to one var using below command.


With the help of hasNext() method you can check whether it is having the next document. And you can also check how many documents still left in the batch.



Projection :

As we have already discussed, projection is used to reduce the output of the find query. I don't want to discuss more on this. You can try it on your own.


Comparison operators:

Below are the list of comparison operators available in MongoDB.
  • $eq  -- Matches values that are equal to a specified value.
  • $gt  --  Matches values that are greater than a specified value.
  • $gte -- Matches values that are greater than or equal to a specified value.
  • $lt  --   Matches values that are less than a specified value.
  • $lte  -- Matches values that are less than or equal to a specified value.
  • $ne  -- Matches all values that are not equal to a specified value.
  • $in  --  Matches any of the values specified in an array.
  • $nin -- Matches none of the values specified in an array.

Let's do some exercises on comparison operators : 








$in and $nin operators are used on Array.

Consider the "name" collection we have created already, let's try $in and $nin operators now.


Below command doesn't return anything since it doesn't has the specified value in the document.


Similarly, let's try one example with $nin operator.



Element query operators :

$exists and $type are called element query operators in MongoDB.

  • $exists : Matches documents that have the specified field.
  • $type : Selects documents if a field is of the specified type.

Let's see some examples for these operators.

In order to check whether the collection "names" has field "State" or not, use the below command.


Yes, it has..Now, let's check for "zip" filed inside "names" collection.


Oops, the collection "names" doesn't has the field "zip", that's why it did return any documents back from the collection.

In order to work with $type operator in MongoDB, you must know what are all the data types available in MongoDB. I recommend you to please go through the MongoDB website.

Let's see one example on $type operator.


In the above example we are checking the field "Name" is of "string" type or not. If yes, it will retrieve the document.

Logical operators :

$or, $and, $not and $nor are available logical operators in MongoDB.

  • $or : Joins query clauses with a logical OR returns all documents that match the conditions of either clause.
  • $and : Joins query clauses with a logical AND returns all documents that match the conditions of both clauses.
  • $not : Inverts the effect of a query expression and returns documents that do not match the query expression.
  • $nor : Joins query clauses with a logical NOR returns all documents that fail to match both clauses.

Let's see one example for each logical operator.




$not operator perform the logical NOT operation on the specified field and it selects the documents that don't match expression.

Use of $and :

As we have already discussed, the below query always perform logical AND operation.


Logical AND is very very useful if you want to check multiple constraints on the same fields. Let's see one example on this.


In above query, we put 2 constraints/conditions on the same field "a". The first constraint is "NOT EQUAL TO NULL" and the second constraint is "THE FIELD EXISTS OR NOT".


Regex operator :

It provides regular expression capabilities for pattern matching strings in queries.

First copy the example data from the below link.


Once you copied the JSON documents, use "insertMany" command to insert these documents into a collection.

Please make sure that the collection didn't already exists.


On successful insertion MongoDB acknowledge the list of ObjectIds.



Our test data is ready. Now, let's start playing with our queries.

First, check whether we have any documents containing the title "War and Peace".



Yes, we have. Now, let's use regular expression on this document.


Oops, it doesn't return anything. Why didn't it return any documents, because, the values in a MongoDB are case sensitive. The value exact is "War and Peace" not "war and peace". Okay, now let's give a try now.


Great, it has returned the document back. In order to get around with case sensitivity, we can use the below command.


Here, "i" indicates that case in-sensitive.

If you want to get the exact matched document, you can use ^ and $ symbols in your regex query.


The above query check the title which is having the word "war" at the beginning and the word "peace" at the end.

We can also use wild characters with regular expression. Let's see one example on this.


The above query looks for "war followed by any number of characters and then peace somewhere in the title".

You can also use the regular expression "$options" option. Let's have a look.



Okay, now let's move on to array operators.

Query array operators :

$all, $elemMatch and $size are called query array operators in MongoDB.

  • $all : Matches arrays that contain all elements specified in the query.
  • $elemMatch : Selects documents if element in the array field matches all the specified $elemMatch conditions
  • $size : Selects documents if the array field is a specified size.

Let's see one by one now. Please insert the below document into "array" collection.


Now, run the below query to check whether the element "cricket" is there in the collection or not. If yes, the find query will return that particular document.


Now, let's see one example on $size.


Here, "$size:3" indicates that the size of the array "likes" is 3. Let's try with "$size:2" now and see whether it is going to return any documents or not.


Oops, it doesn't return anything since the size of the array is not 2.

Now, let's see one example on $elemMatch. The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.

Insert below 2 documents into "scores" collection.

{ _id: 1, results: [ 82, 85, 88 ] }
{ _id: 2, results: [ 75, 88, 89 ] }



The following query matches only those documents where the results array contains at least one element that is both greater than or equal to 80 and is less than 85.


The query returns the following document since the element 82 is both greater than or equal to 80 and is less than 85.





**Next Post : "Delete and Update in MongoDB"






















































































3 comments:

  1. Wonderful blog! I found it while surfing around on Yahoo News. Do you have any suggestions on how to get listed in Yahoo News? I’ve been trying for a while but I never seem to get there! Appreciate it. id cards

    ReplyDelete