https://docs.mongodb.org/manual/core/replica-set-architectures/
Geoffrey Berard / @geofberard
geoffrey.berard@gmail.com
{
_id : 1,
first_name: 'Paul',
surname: 'McCartney',
instruments : ["Guitar", "Bass guitar", "Piano", ...],
address:{
street: '20 Forthlin Road',
city: 'LiverPool',
zip: 'United Kingdom'
}
}
first_name | last_name | birthday |
---|---|---|
Louis | Armstrong | 4 août 1901 |
first_name | last_name | title | birthday |
---|---|---|---|
Louis | Armstrong | 4 août 1901 | |
Paul | McCartney | Sir | 18 June 1942 |
first_name | last_name | title | nickname | birthday |
---|---|---|---|---|
Louis | Armstrong | 04/08/1901 | ||
Paul | McCartney | Sir | 18/06/1942 | |
Gordon Matthew Thomas | Sumner | Sting | 02/10/1951 |
{
first_name: 'Louis',
surname: 'Armstrong',
birthday: '4 août 1901',
},
{
first_name: 'Paul',
surname: 'McCartney',
title: 'Sir',
birthday: '18 June 1942',
},
{
first_name: 'Gordon Matthew Thomas',
surname: 'Sumner',
nickname: 'Sting',
birthday: '2 octobre 1951',
},
{
first_name: 'Louis',
surname: 'Armstrong',
birthday: '4 août 1901',
},
{
first_name: 42,
},
Binary Representation of JSON - 16MB Maximum
{hello: "world"}
Gives in BSON
\x16\x00\x00\x00\x02hello\x00
\x06\x00\x00\x00world\x00\x00
{
first_name: ‘Paul’,
surname: ‘Miller’,
city: ‘London’,
cars: [
{
model: ‘Bentley’,
year: 1973,
value: 100000
},
{
model: ‘Rolls Royce’,
year: 1965,
value: 330000
}
}
}
Contains cluster metadatas
Requirement :
C | Create |
R | Read |
U | Update |
D | Delete |
SQL | MongoDB | |
---|---|---|
Create | Insert | Insert |
Read | Select | Find |
Update | Update | Update |
Delete | Delete | Remove |
{
_id : 1,
first_name: 'Victor',
surname: 'Hugo',
groups : [ "Writer", "Painter"],
}
> db.member.insert({new_document})
WriteResult({ "nInserted" : 1 })
Create the collection if necessary
> db.member.insert({first_name: "John", last_name: "Doe"})
> db.member.insert({first_name: "Jean", last_name: "Dupont", city_of_birth: "Paris"})
Syntax (Index types)
createIndex( { userid: index_type } )
> db.records.createIndex( { userid: 1 } ) // Ascending index
> db.records.createIndex( { userid: -1 } ) // Descending index
Supported file format
$ ./mongoimport --db test --collection zips --file ../../../Downloads/zips.json
Download zips.json
Returning all elements of a collection:
> db.member.find()
{ "_id" : ObjectId("54853dd6dd8fc0fec931fcbc"), "first_name" : "John", "last_name" : "Doe" }
Returning only the first element:
> db.member.findOne()
Formating the result:
> db.member.find().pretty()
{
"_id" : ObjectId("54853dd6dd8fc0fec931fcbc"),
"first_name" : "John",
"last_name" : "Doe"
}
Syntax :
find({query},{keys_filter})
Example
> db.zips.find({state:"NY"},{city:true, _id:false})
{ "city" : "FISHERS ISLAND" }
{ "city" : "NEW YORK" }
{ "city" : "NEW YORK" }
{ "city" : "NEW YORK" }
{ "city" : "GOVERNORS ISLAND" }
{ pop : {$gt : 100000} }
{ pop : {$lte : 100} }
{ city : {$regex : "^A"} }
{ city : {$exists : true} }
{ city : {$type : type_code} }
Overriding query property
{ pop: {$gt: 10000}, pop: {$lt: 50000}}
is equivalent to
{ pop: {$lt: 50000}}
{ groups : "Painter" }
{ groups : { $in : ["Writer", "Sculptor", "Dancer"]}}
{ groups : { $all : ["Painter", "Writer"]}}
Can return :
{
first_name: 'Victor',
surname: 'Hugo',
groups : [ "Writer", "Painter"]
}
{ address : {
number: 6,
street_name: 'Place des Vosges',
city: 'Paris',
zip: '75004'
}})
Or
{ "address.city" : "Paris" }
Can return :
{
first_name: 'Victor',
surname: 'Hugo',
address:{
number: 6,
street_name: 'Place des Vosges',
city: 'Paris',
zip: '75004'
}
}
{ address : { city : "Paris" }})
{ address : {
street_name: 'Place des Vosges',
number: 6,
city: 'Paris',
zip: '75004'
}})
{ pop : {$gt : 100000, $lt : 2000000} }
{ $or : [{state : "NY"} , {state : "NJ"}]}
{ $and : [ {state : "NY"} , {pop : {$gt : 50000} } ] }
{$and:[{$and:[{city:{regex:"^N"}},{$or:[{state:"NY"},{state:"NJ"}]}]},
{pop:{$gt:100000,$lt:150000}}]}
{
$and:[
{ $and:[
{ city : {regex:"^N"} },
{ $or : [
{state:"NY"},
{state:"NJ"}
]}
]},
{ pop : { $gt : 100000 , $lt : 150000 } }
]
}
Cities starting with "N" in New York or New Jersey with a population between 100k and 150k inhabitants
> db.zips.count({find_query})
Or
> db.zips.count({state:"NY"})
> cursor = db.zips.find({state:"MA"},{city:true, _id:false}); null;
Iterating over results :
> cursor.hasNext() // > true
> cursor.next() // > "AGAWAM"
> cursor.next() // > "CUSHMAN"
> cusror.sort({city : -1}) // Sort in reverse alphabetical order
> cursor.limit(5) // Limit the nomber of results to 5
> cusror.skip(3) // Skip 3 elements besore returning the result
They can be combined
> cusror.sort({city : -1}).limit(5).skip(3)
update( {find_query} , {update_query}, {update_params} )
update({surname : "Hugo"},
{surname : "Hugo", groups : [ "Writer", "Painter"]})
on
{
first_name: 'Victor',
surname: 'Hugo',
address:{
number: 6,
street_name: 'Place des Vosges',
city: 'Paris',
zip: '75004'
}
}
will give
{
surname: 'Hugo',
groups : [ "Writer", "Painter"]
}
{$set : {groups : [ "Writer", "Painter"]}}
{$unset : {groups : 1}}
{$rename : {"oldName" : "newName"}}
{$inc : {count : 1}}
{$mul : {price : NumberDecimal("0.5")}}
{$min : {bestPrice : 150}}
{$max : {highScore : 1275000}}
{"groups.2" : "Poet"}
{$push : {groups : "Poet"}}
{$pushAll : {groups : ["Poet","Politician"]}}
{$pop : {groups : 1}} // remove last element
{$pop : {groups : -1}} // remove first element
{$pull : {groups : "Poet"}}
{$pullAll : {groups : ["Poet","Politician"]}}
{$addToSet : {groups : "Poet"}} // Add "Poet"
{$addToSet : {groups : "Poet"}} // Do nothing because exists
=> Upsert
{ upsert : true } // As update third parameter
> db.member.update({surname : "Washington"},
{ $set : {groups : [ "Writer", "Painter"]}},
{ upsert : true })
{ multi : true } // As update third parameter
> db.member.update({},
{ $set : {title : "Mr"}},
{ multi : true })
WriteResult({ "nMatched" : 5, "nUpserted" : 0, "nModified" : 5 })
> db.member.remove({find_query})
> db.member.drop()
> db.zips.explain().find({query});
or
> cur = db.zips.find({query}); null;
> cur.explain()
> db.zips.explain().find({state:"MA"},{city:true, _id:false}).sort({city : -1}).limit(5);
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.zips",
"indexFilterSet" : false,
"parsedQuery" : {
"state" : {
"$eq" : "MA"
}
},
"winningPlan" : ...,
"serverInfo" : {
"host" : "localhost",
"port" : 27017,
"version" : "4.0.4",
"gitVersion" : "f288a3bdf201007f3693c58e140056adf8b04839"
},
"ok" : 1
}
> cur = db.zips.explain("executionStats").find({state:"MA"},{city:true, _id:false}).sort({city : -1}).limit(5); null;
{
"queryPlanner" : {
...
"namespace" : "test.zips",
...
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 5,
"executionTimeMillis" : 20,
"totalKeysExamined" : 0,
"totalDocsExamined" : 29353,
...
},
"serverInfo" : {
"host" : "it-gbe",
"port" : 27017,
"version" : "3.2.11",
"gitVersion" : "009580ad490190ba33d1c6253ebd8d91808923e4"
},
"ok" : 1
}
> db.zips.distinct({field} , {search_query})
> db.zips.distinct("state" , {})
[
"MA",
"RI",
"NH",
...
]
> db.zips.createIndex( { loc : "2d" } )
> db.zips.find( { 'loc': {$near : [ -112.416728, 37.781334 ] } } ).limit(5)
{ "_id" : "84759", "city" : "PANGUITCH", "loc" : [ -112.436886, 37.80777 ], "pop" : 1797, "state" : "UT" }
{ "_id" : "84710", "city" : "ALTON", "loc" : [ -112.548389, 37.469905 ], "pop" : 159, "state" : "UT" }
{ "_id" : "84760", "city" : "PARAGONAH", "loc" : [ -112.773972, 37.89172 ], "pop" : 334, "state" : "UT" }
{ "_id" : "84717", "city" : "BRYCE CANYON", "loc" : [ -112.074311, 37.608427 ], "pop" : 958, "state" : "UT" }
{ "_id" : "84761", "city" : "PAROWAN", "loc" : [ -112.832251, 37.844861 ], "pop" : 1988, "state" : "UT" }
> db.zips.aggregate([{ $group: {group} } , { $match: {group} }])
> db.zips.aggregate([{ $group: { _id: "$city", totalPop: { $sum: "$pop" } } }])
{ "_id" : "CHALKYITSIK", "totalPop" : 99 }
{ "_id" : "WRANGELL", "totalPop" : 2573 }
{ "_id" : "SKAGWAY", "totalPop" : 692 }
{ "_id" : "THORNE BAY", "totalPop" : 744 }
...
Posts
{
_id : ObjectId("54853dd6dd8fc0fec931fcbc"),
title : "Title",
body : "..."
author : "Author",
date : "Date",
comments : [
{
name: "Observer",
comment: "Comment",
}
],
tags: ["Course","MongoDB"]
}
Author
{
_id : "UserName",
email : "UserEmail"
}
...
{ _id : "vHugo", email : "victor.hugo@gmail.com", follower:["gWashington"]}
{ _id : "gWashington", email : "george.washington@gmail.com"}
...
{ _id : "vHugo", email : "victor.hugo@gmail.com"}
{ _id : "gWashington", email : "george.washington@gmail.com"}
{ _id : 1, _from : "gWashington", _to : "vHugo"}
{ _id : "vHugo", email : "victor.hugo@gmail.com"}
{ _id : "gWashington", email : "george.washington@gmail.com"}
{ _id : 1, _from : "gWashington", _to : "vHugo"}
{ _id : 1, _from : "vHugo", _to : "gWashington"}
$ cd path_to_downloaded_file
$ tar xvf mongodb-osx-x86_64-4.0.4.tgz
$ sudo mkdir -p /usr/local/var/mongodb
$ sudo chmod 777 /usr/local/var/mongodb
$ cd mongodb-osx-x86_64-4.0.4/bin
$ ./mongod --dbpath /usr/local/var/mongodb
$ ./mongo
$ cd C:\
$ md "\data\db"
$ cd "C:\Program Files\MongoDB\Server\4.2\bin\"
$ mongod.exe --dbpath="c:\data\db"
$ mongo.exe
Github : goo.gl/xszvRW
Startup project
$ git clone https://github.com/geofberard/MongoNotes.git
$ cd MongoNotes
$ mvn clean install
$ git checkout step-0
Each step of the practical is saved in a special branch.
If you are stuck, you can checkout the next branch to go to the next step with :
$ git reset HEAD --hard
$ git checkout branch_name
(all your current modification will be lost)
The branches are :
$ git checkout step-0
String id; //String extracted from MongoDB ObjectID
String title;
String text;
String type; //Can be description/room/today/theaters
boolean important; //Say if the document is flagger or not
$ git checkout step-1
You need to get all the notes from the collection
There are some hints :
$ git checkout step-2
You need to add a new document in the collection
There are some hints :
$ git checkout step-3
You need to delete a document from the collection
There are some hints :
$ git checkout step-4
You need to update document in the collection
There are some hints :
$ git checkout step-final
You can add a new feature
MongoDB write path
Replication principles
Replica set Read and Write Semantics
Replica set in practice
journal
low level log of an operation for crash recovery (can be turned off)
oplog
similar to RDBMS binlog
stores (idemopotent) high-level transactions that modify the database
kept on the master and used for replication
MongoDB write path
Replication principles
Replica set Read and Write Semantics
Replica set in practice
Replica set = a group of mongod processes that provide redundancy and high availability
Writes: write to single node replicated to the others members of the replica set
Read: read from a single member of the replica set
Disclaimer:
we only consider replica sets without sharding (for now)
we not include proposed MongoDB 3.2 replication modifications (readConcern…)
Primary
acceptes all writes and reads
1 primary per replica set
Secondaries replicates data (and can serve reads ⇒ reads preferences)
Priority 0 ⇒ Hidden members ⇒ Delayed
Arbiters (usually at most one) : break ties
Primary acceptes all writes + reads + records them in oplog
Secondary replicates primary oplogs (also accept reads)
asynchronous oplog replication
heartbeat for monitoring status
member’s priority
latest optime in the oplog
uptime
break the tie rules
cannot become primary
cannot trigger elections
can vote in elections
copy of data + accepts reads
Priority 0 members that don’t accept reads
reflect an delayed state of the set
must be priority 0 ⇒ prevent them to become primary
should be hidden ⇒ prevent application to query stale data
a replica cannot become primary with only 1 vote
majority with even numbers of members ?
use Arbitrers to break ties
does not hold data
cannot became a primary
No primary ⇒ writes no longer possible, reads still accepted
Fault tolerance : number of members that can become unavailable and still be able to elect a primary
https://docs.mongodb.org/manual/core/replica-set-architectures/
a rollback reverts write operations on a former primary when the member rejoins its replica set after a failover
the primary accepted a write that was not sucessfuly replicated to secondaries !
Cause of the problem ?
default write semantics { w:1 } ⇒ the primary acknowledge the write after the local write (local Journal!)
manually apply/discard rollbacks ( rollback/ folder)
avoid rollbacks use { w:majority }
READ UNCOMMITED SEMANTICS
! Regardless of write concern, other clients can see the result of the write operations before the write operation is acknowledged to the issuing client.
! Clients can read data which may be subsequently rolled back.
MongoDB write path
Replication principles
Replica set Read and Write Semantics
Write concerns
Read preferences
Replica set in practice
parameters that change the default read/write semantics (move the CAP cursor)
write concern
is the guarantee an application requires from MongoDB to consider a write operation successful
read preference
applications specify read preference to control how drivers direct read operations to members of the replica set
w:1 (default)
the primary acknowledge the write after the local write
other options:
w:N
ack the write after the ack of N members
x:majority
ack the write after the ack of the majority of the members
optional parameter wtimeout
prevents write operations from blocking indefinitely if the write concern is unachievable
at the query level
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: 2, wtimeout: 5000 } }
)
change the default write concern:
cfg = rs.conf()
cfg.settings = {}
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)
primary (default)
read from the current replica set primary.
primaryPreferred
read from primary (or secondary iff no primary)
secondary
read from secondary members
secondaryPreferred
read from secondary(or primary iff no primary)
nearest
read from the member with the least network latency
Async replication ⇒ stale data if read from replica
Maximize Consistency ⇒ primary read preference
Maximize Availability ⇒ primaryPreferred read preference
Minimize Latency ⇒ nearest read preference
MongoDB write path
Replication principles
Replica set Read and Write Semantics
Replica set in practice
Read the documentation for the systems you depend on thoroughly–then verify their claims for yourself. You may discover surprising results!
read the MongoDB documentation and the Jespen blog entry:
do the replica set tutorial in the MongoDB documentation: