Essentials of MongoDB & Mongo Shell underlying JavaScript

Abhishek koserwal
5 min readOct 12, 2018

--

MongoDB is a free and open-source cross-platform document-oriented database program. wiki

Why may you want to use it? I came across three major questions which might give you an abstract understanding for No-SQL database.

Do you need a flexible data over structure?

Example of flexible data can be: we have two users: User-1 and User-2. We want additional fields defined for User-2. With a relational database. Either you need to defined fields like mobile, address, hobbies etc for both users and kept them empty for User-1.

Flexible data example:-

User1 {
firstName :"John",
lastName: "Doe",
email:"jdoe@example.com",
userId:"jdoe"
}
User2 {
firstName :"Charlie",
lastName :"Sheen",
email:"charlies@example.com",
userId:"csheen",
mobile:"+1-234-xxx-xxx",
address:"Malibu House",
hobbies: {
"Playing piano",
"Driving"
}
}

Do you have vast amount (inconsistency) data to store?

If you have a few users like the above case, still you can consider the relational database. But you have such variations with a large amount of users attributes. You can look for the NoSQL database.

Do you value scaling over consistency ?

This one is the most tricky question, you need to identify your definition/need for scalability in terms of system, network, or process.

Terms like

  • Scale horizontally (distributed system)
  • Scale vertically (enable a single system to add resources to perform well)
  • BASE VS ACID:

ACID

  • Atomic
  • Consistent
  • Isolated
  • Durable

BASE:

  • Basic Availability
  • Soft-state
  • Eventual consistency

Definition of scalability changes with the use-case & each case requires analysis to understand it. It is out of scope to discuss within this article.

If the answers to the above question is yes than NoSQL might be a right choice. Other NoSQL databases you can look forward to being: CouchDB, MongoDB, Apache Cassandra, Hypertable, HBase etc.

Term “database” in MongoDB is more like a namespace for collections. And you collection store documents. It follows a simple format principle

<database/namespace>.<collection>.<operation>

Mongo Shell (MongoDB shell version v 3.4.10)

Basic commands and understanding involved JavaScript concepts.

mongo -h

All the magic starts with mongo.js script where “Mongo” is a JavaScript function (way we define classes in JS).

if (typeof Mongo == "undefined") 
{ Mongo = function(host) {
this.init(host);
};
}

As you can see, Mongo is class with methods define as Prototypal inheritance such as insert, remove, find, update etc i.e crud operations. You can call all this defined method inside shell using `db` keyword.

Checking Databases (namespace for collections);

> show dbs;> use <database-name>;
// if db didn't exists, it will create a new.
> use sample
switched to db sample
// Create a collection
> db.createCollection("userDoc")
{ "ok" : 1 }
// List Collection in the database;> show collectionstest-test
test
example
userDoc

Collections:

> db.userDoc.count()
0
//return count of documents in the collection
> db.test-test.count()
// It will give error due to "-" special character.
> db["test-test"].count()
////return number of documents in the collection
> typeof(db)
//object
> var database = db>database.test.count()
//return count of documents in the collection

Let’s Insert some data into our collection `userDoc`.

Create user object:

As you can see, Mongo follows similar data-type like string, array, objects etc. it stores data in BSON format.

Threshold and limits: https://docs.mongodb.com/manual/reference/limits/

>var user1 =
{
"_id" : 1,
"userID" : "jDoe",
"address" : {
"building" : "230",
"coord" : [
-73.996089,
40.675018
],
"street" : "Huntington St",
"zipcode" : "11231"
},
"email" : "test@example.com",
"languages" : [
{
"speaks" : "English"
},
{
"speaks" : "German"
},
{
"speaks" : ""
}
],
"Bio" : [
{
"summary" : "I am work as software developer",
"date" : ISODate("2013-09-11T00:00:00Z")
},
{
"summary" : "total experience of 3 years",
"date" : ISODate("2013-01-24T00:00:00Z")
}
],
"name" : "John Doe",
"user_id" : "30075445"
}

> db.userDoc.insert(user1);
WriteResult({ "nInserted" : 1 })

Find query:

> var q = db.userDoc.find()
> q
{ "_id" : 1, "userID" : "jDoe", "address" : { "building" : "230", "coord" : [ -73.996089, 40.675018 ], "street" : "Huntington St", "zipcode" : "11231" }, "email" : "test@example.com", "languages" : [ { "speaks" : "English" }, { "speaks" : "German" }, { "speaks" : "" } ], "Bio" : [ { "summary" : "I am work as software developer", "date" : ISODate("2013-09-11T00:00:00Z") }, { "summary" : "total experience of 3 years", "date" : ISODate("2013-01-24T00:00:00Z") } ], "name" : "John Doe", "user_id" : "30075445" }
> print(q)
DBQuery: test.userDoc -> { }
>printjson(q)
{
{<Object>
Supported functions
}

Help: You can check all support methods/defined as prototype functions

>q.help()

find(<predicate>, <projection>) modifiers
.sort({...})
.limit(<n>)
.skip(<n>)
.batchSize(<n>) - sets the number of docs to return per getMore
.collation({...})
.hint({...})
.readConcern(<level>)
.readPref(<mode>, <tagset>)
.count(<applySkipLimit>) - total # of objects matching query. by default ignores skip,limit
.size() - total # of objects cursor would return, honors skip,limit
.explain(<verbosity>) - accepted verbosities are {'queryPlanner', 'executionStats', 'allPlansExecution'}
.min({...})
.max({...})
.maxScan(<n>)
.maxTimeMS(<n>)
.comment(<comment>)
.snapshot()
.tailable(<isAwaitData>)
.noCursorTimeout()
.allowPartialResults()
.returnKey()
.showRecordId() - adds a $recordId field to each returned object

Cursor methods:

Cursor methods
.toArray() - iterates through docs and returns an array of the results
.forEach(<func>)
.map(<func>)
.hasNext()
.next()
.close()
.objsLeftInBatch() - returns count of docs left in current batch (when exhausted, a new getMore will be issued)
.itcount() - iterates through documents and counts them
.getQueryPlan() - get query plans associated with shape. To get more info on query plans, call getQueryPlan().help().
.pretty() - pretty print each document, possibly over multiple lines
> q.hasNext()
false

Using map

var q = db.userDoc.find()
> q.map(x => x)
[
{
"_id" : 1,
"userID" : "jDoe",
"address" : {
"building" : "230",
"coord" : [
-73.996089,
40.675018
],
"street" : "Huntington St",
"zipcode" : "11231"
},
"email" : "test@example.com",
"languages" : [
{
"speaks" : "English"
},
{
"speaks" : "German"
},
{
"speaks" : ""
}
],
"Bio" : [
{
"summary" : "I am work as software developer",
"date" : ISODate("2013-09-11T00:00:00Z")
},
{
"summary" : "total experience of 3 years",
"date" : ISODate("2013-01-24T00:00:00Z")
}
],
"name" : "John Doe",
"user_id" : "30075445"
}
]
> var q =db.userDoc.find()
> q.map(x => x._id)
[ 1 ]
> var q =db.userDoc.find()
> q.map(x => x.userID)
[ "jDoe" ]

Familiar with the concepts of Javascript makes easier to relate concepts with MongoDB And various queries can be designed based on experience with writing Javascript. I’ll try to cover complex queries in another article.

--

--

Abhishek koserwal

#redhatter #opensource #developer #kubernetes #keycloak #golang #openshift #quarkus #spring