Académique Documents
Professionnel Documents
Culture Documents
En revanche ce n'est plus une bonne solution pour des accès globaux à la base (puisqu'il faut alors effectuer
beaucoup de jointures pour reconsolider l'ensemble de l'information).
Identification
Object Identifiers (OID)
Universally Unique IDentifier (UUID)
Uniform Resource Name (URN)
Imbrication
Structure des valeurs stockées connue par le serveur (RO, JSON, XML, structure interne de type colonne...).
Hachage et distribution
Logique de dépôt uniquement (stocker et retrouver) ;
c'est la couche applicative qui fait tout le travail (traitement, cohérence...).
Schema-less
Les bases NoSQL se fondent sur une approche dite schema-less, c'est à dire sans schéma logique défini à
priori.
L'équivalent du CREATE TABLE en SQL n'est pas nécessaire, même pas possible ; on peut directement
faire l'équivalent de INSERT INTO.
Cela apporte de la souplesse et de la rapidité, mais se paye avec moins de contrôle et donc de cohérence
des données.
Le mouvement NoSQL tend à réintégrer des fonctions de schématisation a priori, à l'instar de ce qui se fait
en XML : le schéma est optionnel, mais conseillé en contexte de contrôle de cohérence.
1
Mongo DB
Nous allons consacrer ce chapitre à une base dite “documentaire” qui représente les données
au format JSON. Il s’agit de MongoDB, un des systèmes NoSQL les plus populaires du
moment.
MongoDB n’impose pas de schéma, ce qui peut être vu comme un avantage, mais peut
devenir rapidement pénalisant puisque la charge du contrôle des données est reportée du côté
de l’application.
MongoDB propose un langage d’interrogation qui lui est propre (donc, non standardisé),
pratique mais limité.
Les données utilisées en exemple ici sont celles de notre base de films, que vous pouvez récupérer sur le site du
Webscope, http://webscope.bdpedia.fr/index.php?ctrl=xml. Choisissez bien entendu les exports en JSON. Si
vous disposez de documents JSON plus proches de vos intérêts, vous êtes bien entendu invités à les prendre
comme base d’essai.
Installation de MongoDB
Les Schéma
La première étape de la création d'une base de données relationnelle est de définir son schéma
c'est-à-dire l'ensemble des tables la composant et l'ensemble des champs de ces tables.
Cette étape crée une certaine rigidité dans l'implémentation, implique d'avoir une vision assez
claire des évolutions de l'application et peut poser problème si la structure des données
recueillies change dans le temps.
Les systèmes NoSQL sans-schéma peuvent ignorer cette étape et stocker des données
hétérogènes au fur et à mesure de leur alimentation. Cette utilisation permet une grande
flexibilité et des capacités d'adaptation au niveau de la base de données.
La contrepartie est que les applications qui liront la base de données devront être capables
d'intégrer des données plus hétérogènes et de structure plus complexe.
Marché
Les SGBD relationnels sont largement répandus dans les entreprises. Dimensionnés pour une
quantité d'informations et un nombre d'utilisateurs typiques d'une entreprise, ils ont pour fonction
principale le traitement de transactions.
Ils montrent cependant leurs limites lorsqu'ils sont utilisés dans un périmètre plus large, tel qu'un
site web populaire, fréquenté par des millions de visiteurs dans le monde entier.
Les SGBD relationnels exigeraient alors des logiciels et des ordinateurs coûteux ainsi que des
compétences en optimisation peu répandues.
Ce segment de marché est de ce fait occupé par les logiciels NoSQL, conçus spécifiquement
pour un usage de type Internet (beaucoup de lecture). Ces produits abandonnent la
représentation matricielle de l'information et le langage de commande SQL en échange d'une
simplicité, d'une performance et surtout d'une scalabilité accrues.
Simple à mettre en œuvre, le stockage d'information à l'aide de tableaux associatifs (clé/valeur)
existe depuis le début de l'histoire des bases de données, en 1970.
2
Des langages comme Perl et PHP les ont rendus familiers aux programmeurs. Les nouvelles
demandes en rapport avec les sites web de grande audience apparus dans les années 2000 et la
facilité de mise en œuvre des tableaux associatifs ont fait émerger ces solutions.
Elles ont comme point commun l'abandon du langage SQL et sont donc nommées NoSQL.
3
Exemple : mongo DB
MongoDB est un engin de base de données dans la famille des engins NoSQL. Dans ce
contexte, il n’y a pas de table ou de schéma de structure de données. Les données sont
enregistrées dans des structures nommées Documents.
MongoBD est une base de données open source NoSQL orientée document. Elle stocke des
données au format JSON (en fait BSON, qui est une version binaire de JSON).
Le serveur MongoDB est organisé en plusieurs databases :
Chaque database contient des collections.
Chaque collection contient des documents.
Chaque document est au format JSON et contient des propriétés.
SQL MongoDB
table collection
enregistrement document
La notion de document est la base d’un système NoSQL. Toutefois, sachez que
MongoDB est plus que cela. Par exemple, MongoDB offre:
Schema-less
Mongodb est une base schema-less, une collection peut contenir des
documents de structures différentes et il n'est pas possible de définir la
structure a priori d'une collection.
La structure d'une collection n'est donc définie que par les documents qui
la composent, et elle peut évoluer dynamiquement au fur et à mesure des
insertions et suppressions.
4
Architecture
MongoDB fonctionne sous la forme d'un serveur auquel il est possible de
se connecter avec un client textuel (mongo shell).
MongoDb peut être distribuée sur plusieurs serveurs (partitionnement
horizontal ou sharding) et accédée à travers de multiples couches
applicatives (langages, API...)
Installation de MongoDB
MongoDB est disponible sur Windows, OSX et Linux :
https://docs.mongodb.com/manual/installation
MongoDB nécessite un répertoire pour stocker toutes les données. Par défaut, le chemin de ce
répertoire est \data\db. Créer ce répertoire. On obtient le répertoire c:\data\db.
Ou bien
logpath=C:\data\logs\mongo.log
dbpath=C:\data\db
Vous pouvez spécifier un autre chemin pour les fichiers de données mais en utilisant l'option
Exemple :
5
Pour se connecter à un serveur MongoDB :
présent sur la même machine : exécuter simplement mongo dans un terminal ;
mongod est le processus démon primaire pour le système MongoDB. Il traite les requêtes
sur les données, gère l'accès aux données, et effectue des opérations de traitement en
arrière-plan.
Lancez mongo via une invite de commandes en tapant la commande suivante : mongo
La connexion ne peut réussir que si le service MongoDB est lancé.
Par défaut, mongo recherche un serveur de base de données sur le port 27017 sur
l'interface locale. Pour se connecter à un serveur sur un port ou une interface différente,
utilisez les paramètres --port et --host.
Exemple
use db1
db.col1.insert( { "nom":"salima" } )
6
{ "_id":ObjectId("5dbe32b3286a9a8fad205"), "nom":"salima" }
7
le second document JSON (optionnel) définit une projection.
Exemple
Restriction
db.Cinema.find({"nom":"Honkytonk Man"})
retourne les documents JSON tels qu'ils ont à la racine un attribut "nom" avec la valeur
"Honkytonk Man".
Restriction et projection
db.Cinema.find({"nom":"Honkytonk Man"}, {"nom":1, "realisateur":1} )
retourne les documents JSON tels qu'ils ont à la racine un attribut "nom" avec la valeur
"Honkytonk Man", et seul les attributs situés à la racine "nom" et "realisateur" sont
projetés.
Il est possible de générer des données de test en utilisant une boucle for. À partir du Shell mongo,
tapez la commande suivante :
Les données précédentes peuvent être générées en utilisant une fonction JavaScript :
la base de données ;
le nom de la collection (existante ou non) ;
le nombre de documents à créer.
8
Interroger Mongo en JavaScript
La console mongo permet d’exécuter des programme JavaScript avec
instruction load.
//test.js
2 print("Hello world");
> load("test.js")
while ( recordset.hasNext() ) {
printjson( recordset.next() );
}
9
La méthode « hasNext() » retourne «true» si l'objet «cursor» contient
encore des documents.
var c = db.testData.find()
Pour de très grands volumes de données, mongo peut ainsi manquer de mémoire.
Dans notre cas : retrouvons les documents ayant 7 pour valeur de x, par
exemple. La requête est la suivante :
db.testData.find( { x : 7 } )
10
Obtention d'un document unique d'une collection
db.testData.findOne()
Exemple :
db.testData.find().limit(3)
Insertion
11
# { nom: "Quentin", agenda: { lundi: "programmation", mardi: "dev", mercredi: "code" } }
# on pourra matcher depuis son sous document ainsi (notez bien les guillemets autour
de agenda.mardi) :
db.db1.find().sort({ addedOn: 1 })
db.db1.find().count()
12
Gestion de restaurants
db.restaurants.findOne()
{
"_id" : ObjectId("594b9172c96c61e672dcd689"),
"restaurant_id" : "30075445",
"name" : "Morris Park Bake Shop",
"borough" : "Bronx",
"cuisine" : "Bakery",
"address" : {
"building" : "1007",
"coord" :{"type":"Point","coordinates":[-73.856077,40.848447]},
"street" : "Morris Park Ave",
"zipcode" : "10462"
},
"grades" : [
{"date" : ISODate("2014-03-03T00:00:00.000Z"),"grade" : "A","score" : 2},
{"date" : ISODate("2013-09-11T00:00:00.000Z"),"grade" : "A","score" : 6},
{"date" : ISODate("2013-01-24T00:00:00.000Z"),"grade" : "A","score" : 10},
{"date" : ISODate("2011-11-23T00:00:00.000Z"),"grade" : "A","score" : 9},
{"date" : ISODate("2011-03-10T00:00:00.000Z"),"grade" : "B","score" : 14}
]
}
Parmi ces restaurants ceux afficher qui font de la cuisine italienne. Pour combiner
deux "clés/valeurs", il suffit de faire le document motif donnant quels paires
clés/valeurs sont recherchés :
db.restaurants.find(
{ "borough" : "Brooklyn",
"cuisine" : "Italian" }
)
13
Pour cela, il faut utiliser les expressions régulières avec "/xxx/i" (le i pour "Insensible
à la casse").
db.restaurants.find(
{ "borough" : "Brooklyn",
"cuisine" : "Italian",
"name" : /pizza/i }
db.getCollection('restaurants').find(
{"borough":"Brooklyn",
"cuisine":"Italian",
"name":/pizza/i,
{"name":1}
Le filtrage par valeur exacte n'est pas suffisant pour exprimer tout ce que l'on
souhaiterait trouver dans la collection.
14
On peut utiliser des opérateurs arithmétiques sur les clés (valeur numérique). Pour
cela, il sera préfixé d'un dollar $.
"Plus petit que" en anglais se dit "less than", l'opérateur est donc $lt. Il faut y
associer la valeur souhaitée :
$gt, $gte >, ≥ Plus grand que (greater "a" : {"$gt" : 10}
than)
$lt, $lte <, ≤ Plus petit que (less than) "a" : {"$lt" : 10}
$ne ≄ Différent de (not equal) "a" : {"$ne" : 10}
$in, ∈, Fait parti de (ou ne doit pas) "a" : {"$in" : [10, 12, 15, 18] }
$nin ∉
$or ៴ OU logique "a" : {“$or” : [{"$gt" : 10}, {“$lt” :
5} ] }
$and ៱ ET logique "a" : {“$and” : [{"$lt" : 10}, {“$gt” : 5} ]
}
$not ¬ Négation “a" : {“$not” : {"$lt" : 10} }
$exists ∃ La clé existe dans le “a” : {“$exists” : 1}
document
$size test sur la taille d'une liste “a” : {“$size” : 5}
db.getCollection('restaurants').find(
{"borough":"Manhattan",
"grades.score":{$lt : 10}
},
{"name":1,"grades.score":1, "_id":0})
Ce qui est dérangeant dans ce résultat, c'est le fait que l'on trouve des scores
supérieurs à 10 !
Est-ce que la liste "grades" contient des scores avec une valeur inférieure à 10 ?
Pour ne récupérer que ceux qui n'ont pas de score supérieur à 10, il faut alors
combiner la première opération avec une négation de la condition " ≥10".
15
La condition est alors vérifiée sur chaque élément de la liste.
db.getCollection('restaurants').find(
{"borough":"Manhattan",
"grades.score":{
$lt:10,
$not:{$gte:10}
}
},
{"name":1,"grades.score":1, "_id":0})
Chercher les restaurants qui ont un grade ‘C’ avec un score inférieur à 40.
db.restaurants.find({
"grades.grade" : "C",
"grades.score" : {$lt : 30}
},
{"Grades.grade":1, "grades.score":1}
);
$elemMatch
db.restaurants.find({
"grades" : {
$elemMatch : {
"grade" : "C",
"score" : {$lt :40}
}
}
},
{"grades.grade" : 1,"grades.score" : 1}
);
Distinct
db.restaurants.distinct("borough")
16