MongoDB
Easier to scale
NoSql DBs in general are easier to scale than SQL or relational databases
Faster
NoSql DBs are also faster in more types of operations.
Starting MongoDB after installing it from the MongoDB website using the MSIRun it as an administrator
C:\Program Files\MongoDB\Server\3.6\bin>mongod --directoryperdb --dbpath "C:\Program Files\MongoDB\Server\3.6\data\db" --logpath "C:\Program Files\MongoDB\Server\3.6\log\mongo.log" --logappend --install
C:\Program Files\MongoDB\Server\3.6\bin>net start MongoDB
The MongoDB service is starting......
How to open a mongo shell?
By typing mongo from the bin directory
C:\Program Files\MongoDB\Server\3.6\bin>mongo
MongoDB shell version v3.6.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.2
Welcome to the MongoDB shell.
Get list of DBs
> show dbs
admin 0.000GB
local 0.000GB
Creating own DB
> use mycustomers
switched to db mycustomers
Check current database
> db
mycustomers
MongoDB Syntax reference
https://docs.mongodb.com/manual/reference
Create a user
> db.createUser({
... user: "brad",
... pwd: "1234",
... roles: ["readWrite", "dbAdmin"]
... });
Successfully added user: { "user" : "brad", "roles" : [ "readWrite", "dbAdmin" ] }
>
What is the equivalent of a table in NoSql world?
Collection
What is the equivalent of a row?
Document
(Collection (Document)) :: (Table (Record))
Create a collection
> db.createCollection('customers');
{ "ok" : 1 }
See all collections in the database
> show collections
customers
Insert a document
> db.customers.insert({"first_name":"John", "last_name":"Doe"});
WriteResult({ "nInserted" : 1 })
See the documents in a collection
> db.customers.find()
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "first_name" : "John", "last_name" : "Doe" }
What is the _id field that showed up extra in the find()?
_id is the primary key field.
How is the _id being added a better feature over traditional SQL?
With traditional SQL, you would have to define an Id field, manage the auto increment on it etc.
In NoSQL world, you are free of such responsibilities.
Insert multiple documents
Pass an array to the insert method instead of just an object
> db.customers.insert([{"first_name":"Steven","last_name":"Smith"}, {"first_name":"Joan", "last_name":"Johnson"}]
... );
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
Insert additional field in the structure
> db.customers.insert({"first_name":"Joan","last_name":"Again","gender":"female"});
WriteResult({ "nInserted" : 1 })
How does NoSql fare over Sql in terms of the structure of the data?
With SQL Database, you would have had a table with first_name and last_name initially and at the point that you wanted to add the attribute gender as well, you would have had to go back and change the structure of the table to add the field gender and there after put data in. With NoSql, since there is no explicit schema, you are freely able to add in a document with a different structure than the structure that you have been using so far.
Find again
> db.customers.find()
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "first_name" : "John", "last_name" : "Doe" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805708"), "first_name" : "Steven", "last_name" : "Smith" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
>
Pretty the find results(Format)
> db.customers.find().pretty()
{
"_id" : ObjectId("5a6d56f7fc73b8db66805707"),
"first_name" : "John",
"last_name" : "Doe"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805709"),
"first_name" : "Joan",
"last_name" : "Johnson"
}
{
"_id" : ObjectId("5a6d5906fc73b8db6680570a"),
"first_name" : "Joan",
"last_name" : "Again",
"gender" : "female"
}
Update data
update(match condition, data to be updated);
> db.customers.update({"first_name":"John"},{"first_name":"John","last_name":"Doe","gender":"male"});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify that gender got updated on John
> db.customers.find().pretty();
{
"_id" : ObjectId("5a6d56f7fc73b8db66805707"),
"first_name" : "John",
"last_name" : "Doe",
"gender" : "male"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805709"),
"first_name" : "Joan",
"last_name" : "Johnson"
}
{
"_id" : ObjectId("5a6d5906fc73b8db6680570a"),
"first_name" : "Joan",
"last_name" : "Again",
"gender" : "female"
}
If I have a document with ten fields and I just want to replace one field in it, what would happen if I just pass in the one field that I want changed
> db.customers.update({"first_name":"John"} , {"gender":"male"});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Find
> db.customers.find().pretty();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
//Data only has the one field that was passed. Previously existing attributes were removed.
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805709"),
"first_name" : "Joan",
"last_name" : "Johnson"
}
{
"_id" : ObjectId("5a6d5906fc73b8db6680570a"),
"first_name" : "Joan",
"last_name" : "Again",
"gender" : "female"
}
Ok, so this update mechanism is not the way to set specific fields.
There has to be a different method. How is that done then?
Using $set
Update/Set specific field only
> db.customers.update({"first_name":"Steven"},{$set:{"gender":"male"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify that previous fields are still there for Steven
> db.customers.find().pretty()
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith",
"gender" : "male"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805709"),
"first_name" : "Joan",
"last_name" : "Johnson"
}
{
"_id" : ObjectId("5a6d5906fc73b8db6680570a"),
"first_name" : "Joan",
"last_name" : "Again",
"gender" : "female"
}
Find specific document
> db.customers.find({"first_name":"Steven"}).pretty();
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith",
"gender" : "male",
"age" : 45
}
Increment integer field in a document
Using $inc
> db.customers.update({"first_name":"Steven"},{$inc:{"age":3}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify
> db.customers.find({"first_name":"Steven"}).pretty()
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith",
"gender" : "male",
"age" : 48 // Increased 3 from earlier age of 45
}
Remove a field in a specific document
Use $unset - Specify the field name as the key and the value as 1
> db.customers.update({"first_name":"Steven"},{$unset:{"age":1}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify
> db.customers.find({"first_name":"Steven"}).pretty();
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith",
"gender" : "male"
} // no longer has the age field
Can we remove string field with unset 1 as well?
Yes, as below using exact same syntax as used for number field above.
> db.customers.update({"first_name":"Steven"},{$unset:{"gender":1}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify
> db.customers.find({"first_name":"Steven"}).pretty();
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith"
}
What happens if we try to update a record that does not exist?
No change happens as there is no match.
> db.customers.update({first_name:"Mary"}, {first_name:"Mary", last_name:"John"});
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
Verify
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805708"), "first_name" : "Steven", "last_name" : "Smith" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
>
What if we wanted to create the record if it was not found?
Upsert flag
Add a third options object with one field Upsert whose value is true.
> db.customers.update({first_name:"Mary"}, {first_name:"Mary",last_name:"John"},{upsert:true});
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,//Notice that it shows 1 upserted
"nModified" : 0,
"_id" : ObjectId("5a6d64326e919ce324579aef")
})
Verify
> db.customers.find()
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805708"), "first_name" : "Steven", "last_name" : "Smith" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
Rename field name
Use $rename
> db.customers.update({first_name:"Steven"},{$rename:{"last_name":"lastName"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify
> db.customers.find({first_name:"Steven"}).pretty()
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"lastName" : "Smith" // Notice that the tag changed from last_name
}
Remove a document
> db.customers.remove({first_name:"Steven"});
WriteResult({ "nRemoved" : 1 })
Verify
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
>
Given two Johns, if a remove is done for John,will both Johns be removed?
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
{ "_id" : ObjectId("5a6d6642fc73b8db6680570b"), "first_name" : "John", "last_name" : "Wayne" }
{ "_id" : ObjectId("5a6d6672fc73b8db6680570c"), "first_name" : "John", "last_name" : "Doe" }
Yes - all matched records would be removed
WriteResult({ "nInserted" : 1 })
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
{ "_id" : ObjectId("5a6d6642fc73b8db6680570b"), "first_name" : "John", "last_name" : "Wayne" }
{ "_id" : ObjectId("5a6d6672fc73b8db6680570c"), "first_name" : "John", "last_name" : "Doe" }
> db.customers.remove({first_name:"John"});
WriteResult({ "nRemoved" : 2 })
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
How do we specify that only one record should be removed?
Using justOne flag
> db.customers.find({first_name:"John"});
{ "_id" : ObjectId("5a6d6715fc73b8db6680570d"), "first_name" : "John", "last_name" : "One" }
{ "_id" : ObjectId("5a6d6719fc73b8db6680570e"), "first_name" : "John", "last_name" : "Two" }
> db.customers.remove({first_name:"John"},{justOne:true});
WriteResult({ "nRemoved" : 1 })
> db.customers.find({first_name:"John"});
{ "_id" : ObjectId("5a6d6719fc73b8db6680570e"), "first_name" : "John", "last_name" : "Two" }
Does justOne work with 1 as well as true?
Yes - it does
> db.customers.find({first_name:"John"});
{ "_id" : ObjectId("5a6d6719fc73b8db6680570e"), "first_name" : "John", "last_name" : "Two" }
{ "_id" : ObjectId("5a6d6794fc73b8db6680570f"), "first_name" : "John", "last_name" : "One" }
> db.customers.remove({first_name:"John"},{justOne:1});
WriteResult({ "nRemoved" : 1 })
> db.customers.find({first_name:"John"});
{ "_id" : ObjectId("5a6d6794fc73b8db6680570f"), "first_name" : "John", "last_name" : "One" }
Find with OR clause
Using $or
$or takes an array of objects and each object represent one condition in the OR clause.
> db.customers.find({$or:[{first_name:"Mary"},{first_name:"Joan"}]});
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
Less than operator
lt
> db.customers.find({age:{$lt:40}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Greater than operator
gt
> db.customers.find({age:{$gt:30}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Equal to operator
eq
> db.customers.find({age:{$eq:35}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Greater than or equal to
gte
> db.customers.find({age:{$gte:35}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Less than or equal to
lte
> db.customers.find({age:{$lte:35}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Update a document with a field whose value is another object
> db.customers.update({first_name:"Mary"},{$set:{address:{city:'LA'}}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.customers.find({first_name:"Mary"});
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" } }
Verify
> db.customers.find({first_name:"Mary"});
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" } }
Find by the value of an attribute in a nested object
"SubObject.fieldName"
> db.customers.find({"address.city":"LA"}).pretty()
{
"_id" : ObjectId("5a6d64326e919ce324579aef"),
"first_name" : "Mary",
"last_name" : "John",
"age" : 35,
"address" : {
"city" : "LA"
}
}
Set an array field as an attribute within a document'
> db.customers.update({first_name:"Mary"},{$set:{memberships:["m1","m2","m3"]}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.customers.find({first_name:"Mary"});
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
Matching a value in an array
> db.customers.find({"memberships":"m3"})
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson", "memberships" : [ "m3", "m4" ] }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
> db.customers.find({"memberships":"m2"})
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
Sorting the results
sort with fieldName:1
> db.customers.find().sort({last_name:1});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson", "memberships" : [ "m3", "m4" ] }
{ "_id" : ObjectId("5a6d6794fc73b8db6680570f"), "first_name" : "John", "last_name" : "One" }
Sorting in descending order
sort with field's value as -1
> db.customers.find().sort({last_name:-1})
{ "_id" : ObjectId("5a6d6794fc73b8db6680570f"), "first_name" : "John", "last_name" : "One" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson", "memberships" : [ "m3", "m4" ] }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
count
> db.customers.find().count()
5
limit
> db.customers.find().limit(2);
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson", "memberships" : [ "m3", "m4" ] }
forEach
> db.customers.find().forEach(function(customer){print("First name is " + customer.first_name)});
First name is undefined
First name is Joan
First name is Joan
First name is Mary
First name is John
forEach with lambda expression
> db.customers.find().forEach((customer)=>print(customer.first_name));
[unknown type]
Joan
Joan
Mary
John
Can you do filter as well by any chance?
No
> db.customers.find().filter(true);
2018-01-28T00:13:04.485-0800 E QUERY [thread1] TypeError: db.customers.find(...).filter is not a function
NoSql DBs in general are easier to scale than SQL or relational databases
Faster
NoSql DBs are also faster in more types of operations.
Starting MongoDB after installing it from the MongoDB website using the MSIRun it as an administrator
C:\Program Files\MongoDB\Server\3.6\bin>mongod --directoryperdb --dbpath "C:\Program Files\MongoDB\Server\3.6\data\db" --logpath "C:\Program Files\MongoDB\Server\3.6\log\mongo.log" --logappend --install
C:\Program Files\MongoDB\Server\3.6\bin>net start MongoDB
The MongoDB service is starting......
How to open a mongo shell?
By typing mongo from the bin directory
C:\Program Files\MongoDB\Server\3.6\bin>mongo
MongoDB shell version v3.6.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.2
Welcome to the MongoDB shell.
Get list of DBs
> show dbs
admin 0.000GB
local 0.000GB
Creating own DB
> use mycustomers
switched to db mycustomers
Check current database
> db
mycustomers
MongoDB Syntax reference
https://docs.mongodb.com/manual/reference
Create a user
> db.createUser({
... user: "brad",
... pwd: "1234",
... roles: ["readWrite", "dbAdmin"]
... });
Successfully added user: { "user" : "brad", "roles" : [ "readWrite", "dbAdmin" ] }
>
What is the equivalent of a table in NoSql world?
Collection
What is the equivalent of a row?
Document
(Collection (Document)) :: (Table (Record))
Create a collection
> db.createCollection('customers');
{ "ok" : 1 }
See all collections in the database
> show collections
customers
Insert a document
> db.customers.insert({"first_name":"John", "last_name":"Doe"});
WriteResult({ "nInserted" : 1 })
See the documents in a collection
> db.customers.find()
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "first_name" : "John", "last_name" : "Doe" }
What is the _id field that showed up extra in the find()?
_id is the primary key field.
How is the _id being added a better feature over traditional SQL?
With traditional SQL, you would have to define an Id field, manage the auto increment on it etc.
In NoSQL world, you are free of such responsibilities.
Insert multiple documents
Pass an array to the insert method instead of just an object
> db.customers.insert([{"first_name":"Steven","last_name":"Smith"}, {"first_name":"Joan", "last_name":"Johnson"}]
... );
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
Insert additional field in the structure
> db.customers.insert({"first_name":"Joan","last_name":"Again","gender":"female"});
WriteResult({ "nInserted" : 1 })
How does NoSql fare over Sql in terms of the structure of the data?
With SQL Database, you would have had a table with first_name and last_name initially and at the point that you wanted to add the attribute gender as well, you would have had to go back and change the structure of the table to add the field gender and there after put data in. With NoSql, since there is no explicit schema, you are freely able to add in a document with a different structure than the structure that you have been using so far.
Find again
> db.customers.find()
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "first_name" : "John", "last_name" : "Doe" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805708"), "first_name" : "Steven", "last_name" : "Smith" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
>
Pretty the find results(Format)
> db.customers.find().pretty()
{
"_id" : ObjectId("5a6d56f7fc73b8db66805707"),
"first_name" : "John",
"last_name" : "Doe"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805709"),
"first_name" : "Joan",
"last_name" : "Johnson"
}
{
"_id" : ObjectId("5a6d5906fc73b8db6680570a"),
"first_name" : "Joan",
"last_name" : "Again",
"gender" : "female"
}
Update data
update(match condition, data to be updated);
> db.customers.update({"first_name":"John"},{"first_name":"John","last_name":"Doe","gender":"male"});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify that gender got updated on John
> db.customers.find().pretty();
{
"_id" : ObjectId("5a6d56f7fc73b8db66805707"),
"first_name" : "John",
"last_name" : "Doe",
"gender" : "male"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805709"),
"first_name" : "Joan",
"last_name" : "Johnson"
}
{
"_id" : ObjectId("5a6d5906fc73b8db6680570a"),
"first_name" : "Joan",
"last_name" : "Again",
"gender" : "female"
}
If I have a document with ten fields and I just want to replace one field in it, what would happen if I just pass in the one field that I want changed
> db.customers.update({"first_name":"John"} , {"gender":"male"});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Find
> db.customers.find().pretty();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
//Data only has the one field that was passed. Previously existing attributes were removed.
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805709"),
"first_name" : "Joan",
"last_name" : "Johnson"
}
{
"_id" : ObjectId("5a6d5906fc73b8db6680570a"),
"first_name" : "Joan",
"last_name" : "Again",
"gender" : "female"
}
Ok, so this update mechanism is not the way to set specific fields.
There has to be a different method. How is that done then?
Using $set
Update/Set specific field only
> db.customers.update({"first_name":"Steven"},{$set:{"gender":"male"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify that previous fields are still there for Steven
> db.customers.find().pretty()
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith",
"gender" : "male"
}
{
"_id" : ObjectId("5a6d5878fc73b8db66805709"),
"first_name" : "Joan",
"last_name" : "Johnson"
}
{
"_id" : ObjectId("5a6d5906fc73b8db6680570a"),
"first_name" : "Joan",
"last_name" : "Again",
"gender" : "female"
}
Find specific document
> db.customers.find({"first_name":"Steven"}).pretty();
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith",
"gender" : "male",
"age" : 45
}
Increment integer field in a document
Using $inc
> db.customers.update({"first_name":"Steven"},{$inc:{"age":3}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify
> db.customers.find({"first_name":"Steven"}).pretty()
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith",
"gender" : "male",
"age" : 48 // Increased 3 from earlier age of 45
}
Remove a field in a specific document
Use $unset - Specify the field name as the key and the value as 1
> db.customers.update({"first_name":"Steven"},{$unset:{"age":1}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify
> db.customers.find({"first_name":"Steven"}).pretty();
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith",
"gender" : "male"
} // no longer has the age field
Can we remove string field with unset 1 as well?
Yes, as below using exact same syntax as used for number field above.
> db.customers.update({"first_name":"Steven"},{$unset:{"gender":1}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify
> db.customers.find({"first_name":"Steven"}).pretty();
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"last_name" : "Smith"
}
What happens if we try to update a record that does not exist?
No change happens as there is no match.
> db.customers.update({first_name:"Mary"}, {first_name:"Mary", last_name:"John"});
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
Verify
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805708"), "first_name" : "Steven", "last_name" : "Smith" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
>
What if we wanted to create the record if it was not found?
Upsert flag
Add a third options object with one field Upsert whose value is true.
> db.customers.update({first_name:"Mary"}, {first_name:"Mary",last_name:"John"},{upsert:true});
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,//Notice that it shows 1 upserted
"nModified" : 0,
"_id" : ObjectId("5a6d64326e919ce324579aef")
})
Verify
> db.customers.find()
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805708"), "first_name" : "Steven", "last_name" : "Smith" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
Rename field name
Use $rename
> db.customers.update({first_name:"Steven"},{$rename:{"last_name":"lastName"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Verify
> db.customers.find({first_name:"Steven"}).pretty()
{
"_id" : ObjectId("5a6d5878fc73b8db66805708"),
"first_name" : "Steven",
"lastName" : "Smith" // Notice that the tag changed from last_name
}
Remove a document
> db.customers.remove({first_name:"Steven"});
WriteResult({ "nRemoved" : 1 })
Verify
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
>
Given two Johns, if a remove is done for John,will both Johns be removed?
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
{ "_id" : ObjectId("5a6d6642fc73b8db6680570b"), "first_name" : "John", "last_name" : "Wayne" }
{ "_id" : ObjectId("5a6d6672fc73b8db6680570c"), "first_name" : "John", "last_name" : "Doe" }
Yes - all matched records would be removed
WriteResult({ "nInserted" : 1 })
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
{ "_id" : ObjectId("5a6d6642fc73b8db6680570b"), "first_name" : "John", "last_name" : "Wayne" }
{ "_id" : ObjectId("5a6d6672fc73b8db6680570c"), "first_name" : "John", "last_name" : "Doe" }
> db.customers.remove({first_name:"John"});
WriteResult({ "nRemoved" : 2 })
> db.customers.find();
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
How do we specify that only one record should be removed?
Using justOne flag
> db.customers.find({first_name:"John"});
{ "_id" : ObjectId("5a6d6715fc73b8db6680570d"), "first_name" : "John", "last_name" : "One" }
{ "_id" : ObjectId("5a6d6719fc73b8db6680570e"), "first_name" : "John", "last_name" : "Two" }
> db.customers.remove({first_name:"John"},{justOne:true});
WriteResult({ "nRemoved" : 1 })
> db.customers.find({first_name:"John"});
{ "_id" : ObjectId("5a6d6719fc73b8db6680570e"), "first_name" : "John", "last_name" : "Two" }
Does justOne work with 1 as well as true?
Yes - it does
> db.customers.find({first_name:"John"});
{ "_id" : ObjectId("5a6d6719fc73b8db6680570e"), "first_name" : "John", "last_name" : "Two" }
{ "_id" : ObjectId("5a6d6794fc73b8db6680570f"), "first_name" : "John", "last_name" : "One" }
> db.customers.remove({first_name:"John"},{justOne:1});
WriteResult({ "nRemoved" : 1 })
> db.customers.find({first_name:"John"});
{ "_id" : ObjectId("5a6d6794fc73b8db6680570f"), "first_name" : "John", "last_name" : "One" }
Find with OR clause
Using $or
$or takes an array of objects and each object represent one condition in the OR clause.
> db.customers.find({$or:[{first_name:"Mary"},{first_name:"Joan"}]});
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson" }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John" }
Less than operator
lt
> db.customers.find({age:{$lt:40}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Greater than operator
gt
> db.customers.find({age:{$gt:30}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Equal to operator
eq
> db.customers.find({age:{$eq:35}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Greater than or equal to
gte
> db.customers.find({age:{$gte:35}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Less than or equal to
lte
> db.customers.find({age:{$lte:35}});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35 }
Update a document with a field whose value is another object
> db.customers.update({first_name:"Mary"},{$set:{address:{city:'LA'}}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.customers.find({first_name:"Mary"});
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" } }
Verify
> db.customers.find({first_name:"Mary"});
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" } }
Find by the value of an attribute in a nested object
"SubObject.fieldName"
> db.customers.find({"address.city":"LA"}).pretty()
{
"_id" : ObjectId("5a6d64326e919ce324579aef"),
"first_name" : "Mary",
"last_name" : "John",
"age" : 35,
"address" : {
"city" : "LA"
}
}
Set an array field as an attribute within a document'
> db.customers.update({first_name:"Mary"},{$set:{memberships:["m1","m2","m3"]}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.customers.find({first_name:"Mary"});
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
Matching a value in an array
> db.customers.find({"memberships":"m3"})
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson", "memberships" : [ "m3", "m4" ] }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
> db.customers.find({"memberships":"m2"})
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
Sorting the results
sort with fieldName:1
> db.customers.find().sort({last_name:1});
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson", "memberships" : [ "m3", "m4" ] }
{ "_id" : ObjectId("5a6d6794fc73b8db6680570f"), "first_name" : "John", "last_name" : "One" }
Sorting in descending order
sort with field's value as -1
> db.customers.find().sort({last_name:-1})
{ "_id" : ObjectId("5a6d6794fc73b8db6680570f"), "first_name" : "John", "last_name" : "One" }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson", "memberships" : [ "m3", "m4" ] }
{ "_id" : ObjectId("5a6d64326e919ce324579aef"), "first_name" : "Mary", "last_name" : "John", "age" : 35, "address" : { "city" : "LA" }, "memberships" : [ "m1", "m2", "m3" ] }
{ "_id" : ObjectId("5a6d5906fc73b8db6680570a"), "first_name" : "Joan", "last_name" : "Again", "gender" : "female" }
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
count
> db.customers.find().count()
5
limit
> db.customers.find().limit(2);
{ "_id" : ObjectId("5a6d56f7fc73b8db66805707"), "gender" : "male", "age" : 35 }
{ "_id" : ObjectId("5a6d5878fc73b8db66805709"), "first_name" : "Joan", "last_name" : "Johnson", "memberships" : [ "m3", "m4" ] }
forEach
> db.customers.find().forEach(function(customer){print("First name is " + customer.first_name)});
First name is undefined
First name is Joan
First name is Joan
First name is Mary
First name is John
forEach with lambda expression
> db.customers.find().forEach((customer)=>print(customer.first_name));
[unknown type]
Joan
Joan
Mary
John
Can you do filter as well by any chance?
No
> db.customers.find().filter(true);
2018-01-28T00:13:04.485-0800 E QUERY [thread1] TypeError: db.customers.find(...).filter is not a function
Comments
Post a Comment