########### CREATING COLLECTION #############

1) Create collection (table)
> use Employee



########### INSERTING DOCUMENT #############

1) Insert document (row)
> db.Employee.insert({"Employeeid":1,"EmployeeName":"Martin"})

2) Insert many documents

> var myEmployee = [
... {"Employeeid":1,"EmployeeName":"Smith"},
... {"Employeeid":2,"EmployeeName":"Mohan"},
... {"Employeeid":3,"EmployeeName":"Joe"}
... ];
> db.Employee.insert(myEmployee);

3) Insert custom id field 
> db.Employee.insert({_id:10,"EmployeeName":"Smith"})



########### QUERYING DOCUMENT #############

1) Query (select) documents
> db.Employee.find().forEach(printjson)


2) Querying all documents in a collection
db.Employee.find({})

3) Querying document according to EmployeeName in a collection
db.Employee.find({EmployeeName:"Smith"}).forEach(printjson)

4) Querying document with Employee Id greater than 2 in a collection
 db.Employee.find({Employeeid:{$gt:2}}).forEach(printjson)
 
5) Iterating through a cursor
> var myEmployee = db.Employee.find({Employeeid:{$gt:2}}); // a cursor
> while(myEmployee.hasNext()){print(tojson(myEmployee.next()));} 

6) Limiting query of collection
> db.Employee.find().limit(2).forEach(printjson); // prints in ascending order of objectid

7) Querying in ascending order
> db.Employee.find().sort({Employeeid:-1}).forEach(printjson);

8) Counting number of documents
 >db.Employee.count();

9) Removing document
> db.Employee.remove({Employeeid:2})

10) Updating document
> db.Employee.update({Employeeid:1},{$set:{EmployeeName:"NewJoe"}});

11) Updating multiple properties of a document
 >db.Employee.update({Employeeid:1},{$set:{EmployeeName:"Neo",Employeeid:22}})
 
 ########### BACKING UP #############
 
 1) Copy data files
 
 or
 
 2) Use mongodump to backup to BSON. Resource intensive to run on separate server
 
 
 ########### SYSTEM STATS #############
 
 1) mongostat
 2) mongotop
 3) Web UI - http://localhost:28017
 4) db.serverStatus()
 
 ########### CREATE USER AND ASSIGN ROLE #############
 
 1) Create administrative user
 > db.createUser(
... {user:"Guru99",pwd:"password",
... roles:[{role:"userAdminAnyDatabase",db:"admin"}]})


2) Create single collection admin user> db.createUser(
... {user:"EmployeeAdmin",
... pwd:"password",
... roles:[{role:"userAdmin",db:"Employee"}]
... }
... )

3) Create user with read role for specific database
> db.createUser(
... {
... user:"readEmployee",
... pwd:"password",
... roles:[{role:"read",db:"Employee"}]
... }
... )
Successfully added user: {
        "user" : "readEmployee",
        "roles" : [
                {
                        "role" : "read",
                        "db" : "Employee"
                }
        ]
}

4) Create user with read-write role for specific database
> db.createUser({
... user:"readWriteEmployee",
... pwd:"password",
... roles:[{role:"readWrite",db:"Employee"}]
... }
... )
Successfully added user: {
        "user" : "readWriteEmployee",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "Employee"
                }
        ]
}

########### AUTHENTICATION WITH KERBEROS #############

> use $external

> db.createUser(
... { user:"user1@example.NET",
... roles:[{role:"read",db:"Marketing"}]
... })
Successfully added user: {
        "user" : "user1@example.NET",
        "roles" : [
                {
                        "role" : "read",
                        "db" : "Marketing"
                }
        ]
}


########### REPLICATE SET #############

1) Install mongod on different servers and start them

2) Test connection between them. For example testing connection from Server A to B and C
   mongo --host ServerB --port 27017
   mongo --host ServerC --port 27017
   
3) Create Replica Set (Start first server with Replica Set)
   mongod --replSet "Replica1"
   
4) Initiate Replica Set
   rs.initiate()

5) Test Replicate Set 
   rs.conf()

6) Add servers to Replica Set
   rs.add("ServerB")
   rs.add("ServerC")
   
7) Remove servers from Replica Set

a) Shutdown replica server 
   db.shutdownServer()     
b) From the primary server remove it
   rs.remove("ServerB")

8) Troubleshoot

a) Use rs.status() to send heartbeat messages to each other
b) Print opLog (list of operations) using rs.printReplicationInfo().
   This prints opLog's size and its capacity.   
   
   
########### CREATE INDEX #############   

1) Create index on Employeeid and sort documents by ascending 
  > db.Employee.createIndex({Employeeid:1})
  
2) Create index on multiple properties
   > db.Employee.createIndex({Employeeid:1,Employeename:1})  
   
########### DROP INDEX #############   

1) Drop 1 index
> db.Employee.dropIndex({"Employeeid":1})

2) Drop all indexes
> db.Employee.dropIndexes()   

   
   
######### REGEX ########

1) Search as per regular expression
> db.Employee.find({EmployeeName:{$regex:"Ne"}}).forEach(printjson)   

2) Search as per regular expression with case insensitivity
> db.Employee.find({EmployeeName:{$regex:"Ne",$options:"i"}}).forEach(printjson)

3) Search as per regular expression without regex variable
> db.Employee.find({EmployeeName:/Sm/})

4) Fetch last n documents
> db.Employee.find().sort({Employeeid:-1}).limit(2)



######### SHARDING ########

1) Dividing data into multiple pieces across servers for performance

2) Shard - Basic divided server. Part of Replica Set
   Config Server - Holds config info for cluster
   Router - To send command to correct server

3) 
 a) Make separate server for the config database
    mkdir /data/configdb
 
 b) Start config server
       mongod --configdb ServerD:27019
    
 c) Start the mongo shard instance
       mongos --configdb ServerD:27019
    
 d) Add other shards
    sh.addShard("ServerA:27017")
    sh.addShard("ServerB:27017")
 
 e) Enable sharding for Employee database
    sh.enableSharding(Employeedb);
 
    f) Enable sharding for a collection 
       in the database as per Employeeid field
    starting from range 1
       sh.shardCollection("Employeedb.Employee", { Employeeid: 1 } ) 
 
 
 
################# DROP DATABASE ################
use <database>
db.dropDatabase()