MongoDB : Base de donnée orientée documents.

UE « Systèmes d'Information Tactiques »
Master 2 Génie Logiciel
ISTIC, Université de Rennes 1
Année 2015-2016, second semestre

Emmanuel Caruyer
CR CNRS
Emmanuel.Caruyer@irisa.fr

Logo Université de Rennes 1

Plan du cours

MongoDB : Présentation générale

Développer avec MongoDB

Données géographiques

MongoDB : Bibliographie

MongoDB in action.

MongoDB Reference

MongoDB : Présentation générale

MongoDB : Présentation générale

Logo de MongoDB.

Un SGBD innovant

Un système ouvert et pensé Web

Optimisé pour une disponibilité maximale

Étude d'un exemple : Blog (1)

Schéma entité association blog.

Étude d'un exemple : Blog (2)

Schéma entité association blog.

Étude d'un exemple : Blog (3)

{ 
  _id: ObjectID('4bd9e8e17cefd644108961bb'),

  titre: "La Renault Twizy, entre scooter et citadine",
  auteur: "ecaruyer",

  categories: ["automobile", "écologie", "zéro émission"],

  commentaires: [
    {
      visiteur: "david35", 
      texte: "Merci pour cet article !"
    },
    {
      visiteur: "melody_nelson",
      texte: "Cette voiture est top, mais pêche encore par son autonomie..."
    }
  ],

  texte: "La citadine <strong>Renault Twizy</strong> [...]"
}

Un modèle sans schéma a priori

L'organisation sous forme clé-valeurs

Un SGBD sans jointure ni transaction

Développer avec MongoDB

Utilisation de la console Javascript (1)

Lancement du serveur et de la console

Connexion ou création d'une base de donnée

use <nom_de_la_base>

Insertion d'un document dans une collection

db.<nom_de_la_collection>.insert(<document>)

Lecture d'une collection

db.<nom_de_la_collection>.find([paramètres])

Utilisation de la console Javascript (2)

ecaruyer@victoria ~ $ mongo
MongoDB shell version: 2.4.9
connecting to: test

> use bibliographie
switched to db bibliographie

> document = {
... auteurs: ["Antoine Dupont", "Frédéric Petit"],
... titre: "Databases for the next generation",
... editeur: "University Press",
... pages: 525,
... categories: ["informatique", "vulgarisation", "technologies web"]
... }

> db.articles.insert(document)

> db.articles.find()
{ "_id" : ObjectId("569c5dac1dd328fd9d406fb0"), "auteurs" : [  "Antoine
Dupont",  "Frédéric Petit" ], "titre" : "Databases for the next generation",
"editeur" : "University Press", "pages" : 525, "categories" : [
"informatique",  "vulgarisation"] }

Utilisation de la console Javascript (3)

Modification d'une entrée dans la base

db.articles.find({auteurs: "Antoine Dupont"})
  .update({"$addToSet": {"categories": "technologies web"}})

Modification de tutes les résultats d'une requête

db.articles.find({auteurs: "Antoine Dupont"})
  .update({"$addToSet": {"categories": "technologies web"}}, false, true)

Suppression d'une entrée

db.articles.remove({auteurs: "Antoine Dupont"})

Intéraction à l'aide de l'API Java

// Create a client to connect to the MongoDB server on localhost
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );

// Connect to a specific database. 
// Note: if "mydb" does not exist, it'll be create on the first write. 
MongoDatabase database = mongoClient.getDatabase("bibliographie");

// Retrieve (or create) the collection "articles".
MongoCollection collection = database.getCollection("article");
		
// Make a document and insert it
Document doc = new Document("auteurs", Arrays.asList("Antoine Dupont", "Frédéric Petit"))
               .append("titre", "Databases for the next generation")
               .append("editeur", "University Press")
               .append("categories", Arrays.asList("informatique", "vulgarisation", "technologies web"));

collection.insertOne(doc);

// Query the collection
Document myDoc = collection.find().first();

Écriture d'une requête (1)

Une requête est représentée par un document

db.articles.find({editeur: "University Press"})

On peut enrichir une requête à l'aide d'opérateurs

db.articles.find({pages: {"$gt": 500}})
db.articles.find({auteurs: {"$in": ["Eric Legrand", "Antoine Dupont"]}})
db.articles.find({auteurs: {$not: /^F/}})
db.billets.find({"categories": "automobile", 
                 "commentaires.visiteur": "melody_nelson"}})
db.billets.find({"$or": [{"categories": "automobile"}, 
                         {"commentaires.visiteur": "melody_nelson"}]})

Écriture d'une requête (2)

Récupération d'un sous-ensemble du document (projection)

db.articles.find({editeur: "University Press"},
                 {auteurs: 1})

Tri des résultats

db.articles.find({}).sort({titre: -1})

Améliorer les performances avec un index (1)

Comprendre l'exécution d'une requête : explain()

> db.articles.find({"auteurs.nom": "Dupont"}).explain()
{
	"cursor" : "BasicCursor",
	"isMultiKey" : false,
	"n" : 1,
	"nscannedObjects" : 2,
	"nscanned" : 2,
	"nscannedObjectsAllPlans" : 2,
	"nscannedAllPlans" : 2,
	"scanAndOrder" : false,
	"indexOnly" : false,
	"nYields" : 0,
	"nChunkSkips" : 0,
	"millis" : 0,
	"indexBounds" : {
		
	},
	"server" : "victoria:27017"
}

Améliorer les performances avec un index (2)

Créer un index avec ensureIndex

> db.articles.ensureIndex({"auteurs.nom": 1})
> db.articles.find({"auteurs.nom": "Dupont"}).explain()
{
	"cursor" : "BtreeCursor auteurs.nom_1",
	"isMultiKey" : true,
	"n" : 1,
	"nscannedObjects" : 1,
	"nscanned" : 1,
	"nscannedObjectsAllPlans" : 1,
	"nscannedAllPlans" : 1,
	"scanAndOrder" : false,
	"indexOnly" : false,
	"nYields" : 0,
	"nChunkSkips" : 0,
	"millis" : 0,
	"indexBounds" : {
		"auteurs.nom" : [
			[
				"Dupont",
				"Dupont"
			]
		]
	},
	"server" : "victoria:27017"
}

Données géographiques

Requêtes géographiques (1)

Exemple de collection contenant des données de géolocalisation

{
  "_id" : ObjectId("4d291187888cec7267e55d24"),
  "city" : "New York City",
  "loc" : {
    "lon" : -73.9996
    "lat" : 40.7402,
  },
  "state" : "New York",
  "zip" : 10011
}

Création d'un index géographique

> db.zips.ensureIndex({loc: '2d'})

Requêtes géographiques (2)

Récupération des k plus proches voisins

> db.zips.find({'loc': {$near: [ -73.977842, 40.752315 ]}}).limit(3)

Récupération des enregistrements à l'intérieur d'un disque

> center = [-73.977842, 40.752315]
> radius = 0.011
> db.zips.find({loc: {$within: {$center: [ center, radius ] }}})

Récupération des enregistrements à l'intérieur d'un rectangle

> lower_left = [-73.977842, 40.752315]
> upper_right = [-73.923649, 40.762925]
> db.zips.find({loc: {$within:
{$box: [ lower_left, upper_right ] }}})

Questions ?