MongoDB

SBGD NoSQL
 * écrit en C++
 * tolérance aux pannes par réplication (replicat set)
 * passage à l'échelle (horizontal scaling) en distribuant une base de données entre plusieurs processus mongod (sharding, guide)
 * shell Javascript (plus ...)
 * stockage native des objets JSON
 * support de persistance pour les programmes Node.js (plus ... et Mongoose)

=Liens=
 * http://www.mongodb.org/
 * https://mms.mongodb.com/ : cloud service that makes it easy for you to provision, monitor, backup and scale MongoDB
 * https://mongolab.com/ : MongoDB-as-a-Service

=Documentation=
 * DZone's MongoDB refcard
 * Correspondances avec SQL http://docs.mongodb.org/manual/reference/sql-comparison/
 * Livres https://www.mongodb.org/books

=Premiers pas avec MongoDB=

Lancez le serveur ./bin/mongod --rest --dbpath ./data/db

""Remarque"" : en production, ajoutez les options ./bin/mongod --nohttpinterface --bing_ip --auth --logappend ... --dbpath ./data/db

Ouvrez les pages d'administration via le serveur HTTP et l'interface REST
 * http://localhost:28017/
 * http://localhost:28017/_commands
 * http://127.0.0.1:28017/_replSet

Lancez le shell ./bin/mongo

Quelques commandes d'administration
// Quelques commandes d'administration help

db.help

db.version

db.stats

db.serverStatus

db.currentOp

db.killOp(1234)

prompt=function { return (new Date)+"$ "; }

db.getLastError

// db.serverCmdLinesOpts n'existe plus

db.collection.totalIndexSize

db.collection.getIndexStats

db.shutdownServer

Relancez le serveur mongod

//	show dbs                    show database names show dbs

//	show collections            show collections in current database show collections

//	show users                  show users in current database show users

//	show profile                show most recent system.profile entries with time >= 1ms show profile

//	show logs                   show the accessible logger names show logs

//	show log [name]             prints out the last segment of log in memor show log global

Création et requêtes
// utiliser une base de données : elle devient la base courante pour les opération suivantes use university

//lister les index de la collection persons db.persons.getIndexes

// création d'un index sur lastname pour les requêtes de type : la valeur de la clé lastname est unique // * db.persons.find( { pseudo: "dd" } ) // * db.persons.find.sort( { pseudo: 1 } )

db.persons.ensureIndex( { "pseudo": 1 }, { unique: true } )

// d'autres options sont disponibles : background, sparse, expireAfterSeconds, dropDups

db.persons.getIndexes

db.persons.find

// ajout d'un objet db.persons.save( {   pseudo: "dd",    firstname : "Didier",    lastname : "Donsez",    job : "Professor",    skill : ["Software Engineering","OSGi","IoT"],    hobbies: ["Laser cutter", "DIY"],    likes : 10 } )

db.persons.find

// ajout d'un objet db.persons.save( {   pseudo: "or",    firstname : "Olivier",    lastname : "Richard",    job : "Professor",    skill : ["Network","Grid"],    hobbies: ["3D printing", "DIY"],    likes : 20 } )

db.persons.find

// ajout d'un objet db.persons.save( {   pseudo: "np",    firstname : "Nicolas",    lastname : "Palix",    job : "Professor",    skill : ["Operating Systems","Phycomp","Network"],    address: "Saint Martin d'Hères",    likes : 10 } )

db.persons.find

// rechercher 2 objets db.persons.find.limit(2)

// rechercher un objet db.persons.findOne

// rechercher un objet via l'index db.persons.find( { pseudo : "dd" } ) db.persons.find( { pseudo : "dd" } ).explain

// sortie triée sur le nom db.persons.find.sort( { pseudo: 1 } )

// rechercher les objets dont le champ firstname = "Didier" db.persons.find( { firstname : "Didier" } )

// rechercher les objets dont le champ hobbies n'est pas null db.persons.find( { hobbies : { $ne : null } } )

// rechercher les objets dont le champ hobbies n'existe pas db.persons.find( { hobbies : { $exists: false } } )

var p = db.persons.find while ( p.hasNext ) printjson( p.next.lastname )

Agrégation
// agrégation (type COUNT) par skill : see http://docs.mongodb.org/manual/tutorial/aggregation-with-user-preference-data/ db.persons.aggregate( [    { $unwind : "$skill" },    { $group : { _id : "$skill", number : { $sum : 1 } } },    { $sort : { number : -1 } },    { $limit : 5 }  ] )

// agregation (type COUNT) par map-reduce : see http://docs.mongodb.org/manual/tutorial/map-reduce-examples/

Agrégation par Map-Reduce
var mapFunction1 = function { emit(this.job, this.likes); }; var reduceFunction1 = function(keyjob, valuesLikes) { return Array.sum(valuesLikes); };

db.persons.mapReduce(                    mapFunction1,                     reduceFunction1,                     { out: "map_reduce_example1" }                   )

db.map_reduce_example1.find

var mapFunction2 = function { for (var idx = 0; idx < this.skill.length; idx++) { var key = this.skill[idx]; var value = 1; emit(key, value); }                   };

var reduceFunction2 = function(keySkill, countVals) { count= 0; for (var idx = 0; idx < countVals.length; idx++) { count += countVals[idx]; }                    return count; };

db.persons.mapReduce( mapFunction2,                    reduceFunction2,                     {                       out: { merge: "map_reduce_example2" },                       query: { job: "Professor" }                       // finalize function                     }                   )

db.map_reduce_example2.find

Manipulation de données géographiques GeoJSON
Commandes geoNear, geoSearch

Avec 2dsphere
db.places.insert(  {      loc : { type: "Point", coordinates: [ -73.97, 40.77 ] },      name: "Central Park",      category : "Parks"   } )

db.places.insert(  {      loc : { type: "Point", coordinates: [ -73.88, 40.78 ] },      name: "La Guardia Airport",      category : "Airport"   } )

db.places.ensureIndex( { loc : "2dsphere", category : -1, name: 1 } )

db.places.find( { loc :                 { $geoWithin :                    { $geometry :                      { type : "Polygon",                        coordinates : [ [                                          [ 0 , 0 ] ,                                          [ 3 , 6 ] ,                                          [ 6 , 1 ] ,                                          [ 0 , 0 ]                                        ] ]                } } } } )

db.places.find( { loc :                 { $geoWithin :                    { $centerSphere :                       [ [ -88, 30 ] , 10 / 3959 ]                } } } )

Avec 2d
db.places.ensureIndex( { loc : "2d" },                          { min : -180 , max : +180 , bits : 20} )

db.places.find( { loc :                 { $geoWithin :                     { $box : [ [ 0, 0 ] ,                                [ 100 , 100 ] ]                 } } } )

db.places.find( { loc: { $geoWithin :                         { $center : [ [-74, 40.74 ], 10 ]                } } } )

Avec Haystack Index
A haystack index is a special 2d geospatial index that is optimized to return results over small

db.places.insert({ poi : 100, pos: { lng : 126.9, lat : 35.2 }, type : "restaurant"}) db.places.insert({ poi : 200, pos: { lng : 127.5, lat : 36.1 }, type : "restaurant"}) db.places.insert({ poi : 300, pos: { lng : 128.0, lat : 36.7 }, type : "national park"})

db.places.ensureIndex( { pos : "geoHaystack", type : 1 },                      { bucketSize : 1 } )

db.runCommand( { geoSearch : "places",                search : { type: "restaurant" } ,                 near : [-74, 40.74] ,                 maxDistance : 10 } )

Modification et Suppression
db.persons.update(  { job: "Professor" },   { $inc: { likes: 1 } },   { multi: true } )

// script de modification des champs "address" db.persons.find( { address: {$ne : null}}).forEach(    function update(e) {        var address = e.address;        e.address = new Object;        e.address.way = address;        e.address.city = "";        db.persons.save(e);    } )

// suppression de persons de la collection

db.persons.remove( { job: { $exists: false } } )

exit

Voir les équivalences avec SQL http://docs.mongodb.org/manual/reference/sql-comparison/

./bin/mongostat

Utilisation de l'interface RESTFul

 * http://docs.mongodb.org/ecosystem/tools/http-interfaces/

http://127.0.0.1:28017/university/persons

curl -GET http://127.0.0.1:28017/university/persons

Utilisation avec Node.js et Mongoose
Voir Mongoose

Utilisation avec Node-RED


Il existe dans Node-RED un noeud pour sauvegarder les messages (json) transformés par un flow dans une base MongoDB. Le serveur mongod doit être préalablement démarré.

=Replication= http://docs.mongodb.org/manual/replication/

=Sharding= http://docs.mongodb.org/manual/core/sharding-introduction/