Table des matières
Dernière mise-à-jour : 2020/02/21 07:43
LRF151 - Administration du Serveur MongoDB sous RHEL 7
Dans cette formation vous allez apprendre :
- Ce qui est le NOSQL,
- Ce qui est MongoDB,
- Comment installer et configurer MongoDB,
- Comment utiliser le client mongo,
- Quels sont les clients graphiques disponibles pour MongoDB,
- Quelle est la structure des données de MongoDB,
- Quel est le langage des requêtes de MongoDB,
- Comment utiliser ce langage efficacement.
Présentation
Qu'est-ce le NOSQL ?
La naissance des outils NOSQL (Not Only SQL) a ses origines dans les limitations des propriétés ACID. En effet, c'est les grandes sociétés du web, qui, amenées à traiter des volumes de données très importants, ont été les premières confrontées aux limitations intrinsèques des SGBD relationnels traditionnels.
De ce fait, chaque société a adopté ou a dévélopé sa propre solution de gestion de données :
- Google - BigTable (Fr),
- Facebook - Cassandra (Fr) puis HBase (Fr),
- Ubuntu One - CouchDB (Fr),
- Baidu - Hypertable (Fr),
- Amazon - Dynamo (En)
- LinkedIn - Voldemort (En),
- SourceForge.net - MongoDB.
C'est à travers de ce dernier que ce cours propose de vous faire découvrir la mouvance NOSQL.
Présentation de MongoDB
Dans le cas de MongoDB, les données prennent la forme de documents enregistrés dans des collections. Une collection peut contenir un nombre quelconque de documents. Cependant, les champs d'un enregistrement sont libres et peuvent être différents d'un enregistrement à un autre dans la même collection. Le seul champ commun et obligatoire est le champ de la clé principale : _id.
Fonctionnalités de MongoDB
- La réplication permet de dupliquer les serveurs de base de données pour répondre à une montée en charge ou une tolérance de panne,
- Le Sharding (distribution de données sur plusieurs machines pour assurer la scalabilité) permet de répartir les données sur plusieurs serveurs soit pour simplement augmenter les performances soit pour répartir les données géographiquement,
- Système de fichiers GridFS qui permet de stocker simplement des fichiers en base de données,
- Le SIG ou Système d’Information Géographique permet de manipuler simplement des positions sur un plan ou sur le globe terrestre,
- La fonction de recherche : MongoDB intègre un système de recherche optimisé en fonction de la langue utilisée,
- MongoDB offre des nombreuses fonctionnalités que l’on trouve dans le monde relationnel (count, groupBy, etc.) mais aussi le support de la recherche full-text, la recherche géo-spatiale ou MapReduce (manipulation et distribution de données dans un cluster),
- Supporte l’indexation pour l’optimisation des recherches.
Historique du Projet
MongoDB (de Humongous qui veut dire énorme ou immense) :
- est développé depuis 2007 par MongoDB,
- a été industriellement viable en 2010 avec la version 1.4,
- est écrit en langage C++.
Versions Majeures
Version de MongoDB | Améliorations par rapport à la version précédente |
---|---|
MongoDB 1.2.x | Création d'index plus rapide Fonctions JavaScript stockées La commande fsync configurable Plusieurs petites fonctionnalités et corrections |
MongoDB 1.4 | Amélioration de la mémoire d'indexation Une meilleure détection des expressions régulières |
MongoDB 1.6 | L'option w (et wtimeout) peut se propager vers plusieurs serveurs La commande findAndModify supporte les upserts Option $ showDiskLoc permet de voir l'emplacement du disque d'un document Prise en charge des sockets IPv6 et UNIX |
MongoDB 1.8 | Mode écriture avant Journaling pour faciliter la récupération du crash et la durabilité dans le moteur de stockage Correction d'un problème de concurrence avec de nombreuses connexions entrantes |
MongoDB 2.0 | Journaling est activé par défaut dans la version 2.0 pour les versions 64 bits La commande compact est maintenant disponible pour le compactage des index Réduction de la taille de la pile par défaut Améliorations des Indices de performance Les applications peuvent maintenant utiliser l' authentification avec les clusters fragmentées |
MongoDB 2.2 | Opérations d'agrégation Collections TTL permet supprimer les données périmées d'une collection Augmentation de la capacité du serveur pour les opérations simultanées Amélioration de la sensibilisation Data Center avec Tag Aware Sharding |
MongoDB 2.4 | Fonctionnalité Text Search Ajout d'un nouvel indice de 2dsphere Ajout d'un Index Hashed pour indexer des documents Améliorations de la sécurité |
MongoDB 2.6 | Agrégation Améliorées Text Search activé par défaut Nouveau protocole d'écriture Package MSI pour MongoDB Disponible pour Windows |
MongoDB 3.0 | MongoDB 3.0 introduit le WiredTiger comme moteur de stockage Amélioration du moteur de stockage MMAPv Augmentation du nombre de Replica Set Members Amélioration des Clusters fragmentées Améliorations des requêtes |
MongoDB 3.2 | WiredTiger comme moteur par défaut de stockage Amélioration des Clusters Index partiels disponibles pour indexer des documents Nouveaux opérateurs de requête SpiderMonkey JavaScript Engine |
Exécutables
Le tableau suivant indique les noms des exécutables selon la base de donnée utilisée :
MongoDB | MySQL | Oracle | Informix | DB2 | |
---|---|---|---|---|---|
Serveur | mongod | mysqld | oracle | IDS | DB2 Server |
Client | mongo | mysql | sqlplus | DB-Access | DB2 Client |
Avantages et Inconvénients
Avantages
MongoDB :
- ne nécessite pas de schéma prédéfini des données d'où sa grande flexibilité,
- est une base de données orientée documents qui s’adapte parfaitement à de nombreuses applications, telles les applications de gestion de dossiers, factures, commandes ou produits,
- supporte une évolutivité à la charge (scaling) par l'ajout de machines,
- supporte des indexes secondaires,
- propose un langage complet de requêtes et une stricte cohérence et stabilité,
- propose du calcul en mémoire, d'où la lecture et écriture rapides,
- propose la réplication en mode maître/esclave et le basculement automatique,
- propose le Sharding (répartition automatique de données sur plusieurs machines).
Inconvénients
MongoDB :
- n'a pas de possibilité de réaliser de jointures, les données sont généralement embarquées dans le même document,
- ne peut pas gérer de transactions complexes,
- impose que la charge du contrôle des données soit reportée du côté de l’application puisque il n'y a pas de schéma,
- propose un langage d’interrogation qui lui est propre (donc, non standardisé), pratique mais qui s'avère limité.
Installation de MongoDB
Créez le fichier /etc/yum.repos.d/mongodb-org-3.2.repo :
[root@centos7 ~]# vi /etc/yum.repos.d/mongodb-org-3.2.repo [root@centos7 ~]# cat /etc/yum.repos.d/mongodb-org-3.2.repo [mongodb-org-3.2] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.2/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-3.2.asc
Installez mongo :
[root@centos7 ~]# yum install mongodb-org Loaded plugins: fastestmirror, langpacks adobe-linux-x86_64 | 2.9 kB 00:00:00 base | 3.6 kB 00:00:00 extras | 3.4 kB 00:00:00 mongodb-org-3.2 | 2.5 kB 00:00:00 updates | 3.4 kB 00:00:00 (1/6): adobe-linux-x86_64/primary_db | 2.7 kB 00:00:01 (2/6): extras/7/x86_64/primary_db | 101 kB 00:00:00 (3/6): base/7/x86_64/group_gz | 156 kB 00:00:01 (4/6): mongodb-org-3.2/7/primary_db | 72 kB 00:00:02 (5/6): base/7/x86_64/primary_db | 5.7 MB 00:00:03 (6/6): updates/7/x86_64/primary_db | 2.8 MB 00:00:02 Determining fastest mirrors * base: ftp.ciril.fr * extras: ftp.ciril.fr * updates: centos.crazyfrogs.org Resolving Dependencies --> Running transaction check ---> Package mongodb-org.x86_64 0:3.2.16-1.el7 will be installed --> Processing Dependency: mongodb-org-tools = 3.2.16 for package: mongodb-org-3.2.16-1.el7.x86_64 --> Processing Dependency: mongodb-org-shell = 3.2.16 for package: mongodb-org-3.2.16-1.el7.x86_64 --> Processing Dependency: mongodb-org-server = 3.2.16 for package: mongodb-org-3.2.16-1.el7.x86_64 --> Processing Dependency: mongodb-org-mongos = 3.2.16 for package: mongodb-org-3.2.16-1.el7.x86_64 --> Running transaction check ---> Package mongodb-org-mongos.x86_64 0:3.2.16-1.el7 will be installed ---> Package mongodb-org-server.x86_64 0:3.2.16-1.el7 will be installed ---> Package mongodb-org-shell.x86_64 0:3.2.16-1.el7 will be installed ---> Package mongodb-org-tools.x86_64 0:3.2.16-1.el7 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================================================================================================================================ Package Arch Version Repository Size ================================================================================================================================================================================================ Installing: mongodb-org x86_64 3.2.16-1.el7 mongodb-org-3.2 5.8 k Installing for dependencies: mongodb-org-mongos x86_64 3.2.16-1.el7 mongodb-org-3.2 5.7 M mongodb-org-server x86_64 3.2.16-1.el7 mongodb-org-3.2 13 M mongodb-org-shell x86_64 3.2.16-1.el7 mongodb-org-3.2 6.8 M mongodb-org-tools x86_64 3.2.16-1.el7 mongodb-org-3.2 41 M Transaction Summary ================================================================================================================================================================================================ Install 1 Package (+4 Dependent packages) Total download size: 66 M Installed size: 202 M Is this ok [y/d/N]: y
Activez et démarrez le service :
[root@centos7 ~]# systemctl status mongod ● mongod.service - SYSV: Mongo is a scalable, document-oriented database. Loaded: loaded (/etc/rc.d/init.d/mongod; bad; vendor preset: disabled) Active: inactive (dead) Docs: man:systemd-sysv-generator(8) [root@centos7 ~]# systemctl enable mongod mongod.service is not a native service, redirecting to /sbin/chkconfig. Executing /sbin/chkconfig mongod on [root@centos7 ~]# systemctl start mongod [root@centos7 ~]# systemctl status mongod ● mongod.service - SYSV: Mongo is a scalable, document-oriented database. Loaded: loaded (/etc/rc.d/init.d/mongod; bad; vendor preset: disabled) Active: active (running) since Mon 2017-09-18 13:46:09 CEST; 4s ago Docs: man:systemd-sysv-generator(8) Process: 14244 ExecStart=/etc/rc.d/init.d/mongod start (code=exited, status=0/SUCCESS) CGroup: /system.slice/mongod.service └─14255 /usr/bin/mongod -f /etc/mongod.conf Sep 18 13:46:08 centos7.fenestros.loc systemd[1]: Starting SYSV: Mongo is a scalable, document-oriented database.... Sep 18 13:46:08 centos7.fenestros.loc runuser[14251]: pam_unix(runuser:session): session opened for user mongod by (uid=0) Sep 18 13:46:09 centos7.fenestros.loc mongod[14244]: Starting mongod: [ OK ] Sep 18 13:46:09 centos7.fenestros.loc systemd[1]: Started SYSV: Mongo is a scalable, document-oriented database..
Le client MongoDB est invoqué avec la commande mongo :
[root@centos7 ~]# mongo MongoDB shell version: 3.2.16 connecting to: test Welcome to the MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see http://docs.mongodb.org/ Questions? Try the support group http://groups.google.com/group/mongodb-user Server has startup warnings: 2017-09-18T13:46:09.416+0200 I CONTROL [initandlisten] 2017-09-18T13:46:09.416+0200 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 4096 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files. > exit bye [root@centos7 ~]#
Configuration
Le fichier de configuration de mongodb est /etc/mongod.conf :
[root@centos7 ~]# cat /etc/mongod.conf systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log storage: dbPath: /var/lib/mongo journal: enabled: true processManagement: fork: true # fork and run in background pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile net: port: 27017 bindIp: 127.0.0.1
Dans ce fichier, sont notamment définit le lieu de stockage des données et des logs respectivement dans /var/lib/mongo et /var/log/mongodb/mongod.log par défaut.
Le client Mongo
Une manipulation intéressante à faire consiste à modifier le prompt du client mongo pour afficher la base de donnée courante. Par défaut le prompt est minimaliste :
>
Pour connaître le base de donnée sur laquelle on travaille il convient de de taper “db”
>db test >
Créez donc le fichier $HOME/.mongorc.js :
[root@centos7 ~]# vi $HOME/.mongorc.js [root@centos7 ~]# cat $HOME/.mongorc.js prompt = function(){return db+">";}
Constatez que la base de données courante se trouve dans le prompt :
[root@centos7 ~]# mongo MongoDB shell version: 3.2.16 connecting to: test Server has startup warnings: 2017-09-18T13:46:09.416+0200 I CONTROL [initandlisten] 2017-09-18T13:46:09.416+0200 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 4096 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files. test>
Autres Clients Mongodb
Interfaces graphiques
RoboMongo
RoboMongo est un client graphique disponible pour toutes les plate-formes sur le site https://robomongo.org/. L’installation est très simple :
A Faire - Installez RoboMongo et connectez-vous à MongoDB.
RockMongo
RockMongo est une application PHP disponible sur le site http://www.rockmongo.com et qui nécessite un serveur Apache/PHP. De plus, il est nécessaire d’installer l’extension PHP de connexion à MongoDB.
Genghis
Genghis est une interface d'administration de bases de données NoSQL sous MongoDB permettant une lecture adaptée à chaque périphérique. Il s'agit d'une interface semblable a l'outil phpMyAdmin :
Les API pour MongoDB (Application Programming Interface)
Pour le langage Java
Java-MongoDB-Driver est le pilote Java pris en charge pour MongoDB :
- com.mongodb - il s'agit du paquet de base permettant de créer une connexion client à une instance en cours d' exécution mongod
- com.mongodb.client - ce paquet permet l'accès à une base de données MongoDB
On se connecte à une instance MongoDB en cours d' exécution sur le localhost (port par défaut 27017)
Pour gérer les documents dans l'application, on utilise les paquets suivants :
- org.bson.Document
- com.mongodb.MongoClient
- com.mongodb.client.MongoCollection
- com.mongodb.client.MongoDatabase
Pour le langage C++
mongo-cxx-driver permet de se connecter à une instance mongod et de créer une connexion client à une instance en cours d'exécution mongod.
- La librairie bsoncxx permet de gérer les documents.
Pour gérer les applications, on doit inclure bson/bson.h dans le fichier code de l'application afin de pouvoir gérer les documents.
Structure des Données
Notions de Documents
On associe les documents aux bases de données orientées documents qui sont destinées aux applications qui gèrent des documents. Ce type de bases de données peut être ou non une sur-couche d'une base de données relationnelle.
Dans un système de base de données relationnelles, les informations sont stockées par ligne dans des tables. Ces tables sont mises en relation en utilisants des clés primaires et étrangères. Or dans MongoDb, l'information est modélisée sur un document au format BSON basé sur JSON (Javascript Object Notation).
MongoDB ne nécessite donc pas de schéma prédéfini comme en SQL, il n'est pas nécessaire par exemple de définir des colonnes avec un nom et un type et on peut insérer n'importe quel document BSON. Lors de l'insertion d'un document, MongoDB ajoute automatiquement un index nommé par défaut _id. La méthode insert retourne l'identifiant du document inséré.
De plus, contrairement aux bases de données SQL, il n'est pas nécessaire de faire des requêtes avec des jointures pour connaitre des informations. Dans MongoDb, il suffit de lire le document qui nous intéresse, d'où l'avantage de modéliser les données sur un document.
Notions de Collections
Le terme collection est issu du monde NoSQL et correspond par analogie à la notion de table dans les bases de données relationnelles (MySQL, PosgreSQL, Microsoft Access, Oracle, etc.). Une collection permet de stocker des documents, notion analogue à celle de l'enregistrement.
En comparant le schéma de structure d'une base de MongoDB à celui d'une base de donnée relationelle comme SQL, on peut faire le parallèle suivant:
Base de données relationnelle (SQL) | Base de données NoSQL (MongoDB) |
---|---|
database | database |
table | collection |
row | document où document BSON |
column | field |
index | index |
primary key | primary key |
Pour avoir un apercu, on peut définir par exemple 2 documents comme ceci:
{_id: "Her", acteurs : [{nom:"Johansson", prenom:"Scarlett"}, {nom:"Phoenix", prenom:"Joaquim"}]} {_id: "Avengers", acteurs : [{nom:"Johansson", prenom:"Scarlett"}]}
Dans l'exemple ci-dessus, on peut voir que l'actrice [{nom:“Johansson”, prenom:“Scarlett”}] est dupliquée. Dans le monde NoSQL, on n'hésite pas à dénormaliser le schéma de la base de données pour favoriser les performances à la lecture. L'important est de savoir quelles requêtes seront faites pour décider du format des documents.
Le Format JSON
JSON, ou JavaScript Object Notation, est un format de données textuelles dérivé de la notation des objets du langage JavaScript. Il permet de représenter de l’information structurée.
Un document JSON a pour fonction de représenter de l'information accompagnée d'étiquettes permettant d'en interpréter les divers éléments, sans aucune restriction sur le nombre de celles-ci. Un document JSON ne comprend que deux types d'éléments structurels : des ensembles de paires nom/valeur et des listes ordonnées de valeurs.
Ce format se base donc sur 2 types d'éléments:
- la paire clé/valeur, par exemple “nom”: “Phoenix”
- le tableau, par exemple “couleurs-primaires” : [“cyan”, “jaune”, “magenta”]
Le Format BSON
Le format BSON ou Binary JSON correspond au format des données manipulés par MongoDB. C'est un format d'échange de données informatiques utilisé principalement comme stockage de données et format de transfert de données par le réseau dans la base de données MongoDB. C'est un format binaire permettant de représenter des structures de données simples et des tableaux associatifs (appelées objets ou des documents dans MongoDB). Le nom BSON est basé sur le terme JSON.
Comparaison BSON/JSON
Voici un tableau comparatif de BSON ET JSON :
Comparaison BSON/JSON | ||
---|---|---|
Type de Champs | JSON | BSON |
Number | X | X |
String | X | X |
Boolean | X | X |
Array | X | X |
Object | X | X |
Null | X | X |
Float | - | X |
Date | - | X |
Regular Expression | - | X |
JavaScript Code | - | X |
On constate que le format BSON supporte plus de types que le format JSON. Le codage BSON complète la représentation JSON en y ajoutant des types de données supplémentaires, tels que les formats virgule flottante ou date entre autres.
Format d'un Document BSON
Dernièrement, voici un document au format BSON stockant des informations concernant un film :
{ "_id": "movie:100", "title": "The Social network", "summary": "On a fall night in 2003, Harvard undergrad and programming genius Mark Zuckerberg sits down at his computer and heatedly begins working on a new idea. (...)", "year": 2010, "director": {"last_name": "Fincher", "first_name": "David"}, "actors": [ {"first_name": "Jesse", "last_name": "Eisenberg"}, {"first_name": "Rooney", "last_name": "Mara"} ] }
Le Langage des Requêtes
Requêtes de base
Se placer dans une base de données/Créer une base de données
Pour se placer dans une base de données ou créer une base inexistente, il convient d'utiliser la requête use :
use <database>
Créer une collection
Pour créer une collection, il convient d'utiliser la requête db.createCollection(<collection>) :
db.createCollection("movies")
Important - Une base est constituée d’un ensemble de collections, l’équivalent d’une table en relationnel.
Visualiser la liste des collections
Pour visualiser la liste des collections, il convient d'utiliser la requête show :
show collections
Inserer un document BSON dans une collection
Pour inserer un document BSON dans une collection, il convient d'utiliser la requête db.<collection>.insert (<document>) :
db.movies.insert ({"title": "Batman", "year": 1989}) db.movies.insert ({"produit": "Grulband", prix: 230, enStock: true})
Important - Notez que la structure du deuxième document n’a rien à voir avec le premier. Il n’y a pas de schéma (et donc pas de contrainte) dans MongoDB. On est libre de tout faire, ce qui revient à reporter les problèmes (contrôles, contraintes, tests sur la structure) vers l’application. Notez aussi que lorsque l'on veut insérer des documents BSON dans la base MongoDB, au lieu de les insérer un par un, on peut utiliser l’utilitaire d’import de MongoDB, qui prend en entrée un tableau BSON contenant la liste des objets à insérer.
Affecter un identifiant explicitement
Pour affecter un identifiant explicitement, il convient d'utiliser la requête db.<collection>.insert(<document>) en spécifiant la valeur de _id :
db.movies.insert ({_id: "1", "produit": "Kramölk", prix: 10, enStock: true})
Remplacer un document
Pour remplacer un document, il convient d'utiliser la requête db.<collection>.update(<document>) :
db.movies.update( { "title": "Mr Smith" }, { "title": "Mr Cool", "year": 2000 } )
Modifier des champs d’un document
Pour modifier des champs d’un document, il convient d'utiliser la requête db.<collection>.update(<document>) et $set :
db.movies.update( { "title": "Avengers" }, { $set: { "summary": "c'est un film divertissant" } } )
Compter le nombre de documents dans la collection
Pour compter le nombre de documents dans la collection, il convient d'utiliser la requête db.<collection>.count() :
db.movies.count()
Supprimer un document
Pour supprimer un ou plusieurs documents il convient d'utiliser la requête db.<collection>.remove(<document>) à laquelle on passe en paramètre le query permettant d’identifier les documents visés :
db.movies.remove({"produit": "Grulband"})
Supprimer un champ dans un document
Pour supprimer un champ dans un document, il convient d'utiliser la requête db.<collection>.update(<document>) et $unset :
db.movies.update({"title": "Batman"}, {$unset : {year : 1989}})
Supprimer une collection
Pour supprimer une collection, il convient d'utiliser la requête db.<collection>.drop() :
db.movies.drop()
Trier des documents
Pour trier les documents, il convient d'utiliser la requête db.movies.find ().sort().skip().limit() :
db.movies.find ().sort({"title": 1}).skip(9).limit(12)
Important - Notez qu'implicitement, cela suppose qu’il existe un ordre sur le parcours des documents. Par défaut, cet ordre est dicté par le stockage physique: MongoDB fournit les documents dans l’ordre où il les trouve (dans les fichiers). On peut trier explicitement, ce qui rend le résultat plus déterministe.
Rechercher des documents dans une collection
Pour afficher les contenu d'une collection, il convient d'utiliser la requête db.<collection>.find(<document>) :
db.movies.find()
On obtient des objets (javascript, encodés en BSON), par exemple :
{ "_id" : ObjectId("5422d9095ae45806a0e66474"), "nom" : "nfe024" }
Important - Notez que MongoDB associe un identifiant unique à chaque document, de nom conventionnel _id, et lui attribue une valeur si elle n’est pas indiquée explicitement.
Il est aussi possible de rechercher en connaissant l’identifiant :
db.movies.find ({"_id": "movie:2"})
ou en utilisant n’importe quel attribut :
db.movies.find ({"title": "Alien"})
Projections
Les requêtes précédentes ramènent l’intégralité des objets satisfaisant les critères de recherche. Il est aussi possible de faire des projections, en passant un second argument à la fonction find() :
db.movies.find ({"actors.last_name": "Tarantino"}, {"title": true, "actors": 'j'} )
Le second argument est un objet BSON dont les attributs sont ceux à conserver dans le résultat. La valeur des attributs dans cet objet-projection ne prend que deux interprétations. Toute valeur autre que 0 ou null indique que l’attribut doit être conservé. Si on choisit au contraire d’indiquer les attributs à exclure, on leur donne la valeur 0 ou null. Par exemple, la requête suivante retourne les films sans les acteurs et sans le résumé :
db.movies.find ({"actors": null, "summary": 0})
Opérateurs ensemblistes
Les opérateurs du langage SQL in, not in, any et all se retrouvent dans le langage d’interrogation. La différence, notable, est que SQL applique ces opérateurs à des relations (elles-mêmes obtenues par des requêtes) alors que dans le cas de MongoDB, ce sont des tableaux JSON. MongoDB ne permet pas d’imbriquer des requêtes.
Par exemple, on cherche les films dans lesquels joue au moins un des artistes dans une liste dont on connaît l’identifiant :
db.artists.find({"actors._id": {$in: ["artist:34","artist:98","artist:1"]}})
Le not in correspond à l’opérateur $nin.
db.artists.find({"_id": {$nin: ["artist:34","artist:98","artist:1"]}})
Comme dernier example, voici comment trouver les films qui n’ont pas d’attribut summary :
db.movies.find({"summary": {$exists: false}}, {"title": 1})
Opérateurs booléens
Par défaut, quand on exprime plusieurs critères, c’est une conjonction (and) qui est appliquée. On peut l’indiquer explicitement. Voici la syntaxe (les films tournés avec Leonardo DiCaprio en 1997) :
db.movies.find({$and : [{"year": "1997"}, {actors.last_name: "DiCaprio"]} )
L’opérateur and s’applique à un tableau de conditions. Bien entendu il existe un opérateur or avec la même syntaxe. Les films parus en 1997 ou avec Leonardo DiCaprio :
db.movies.find({$or : [{"year": "1997"}, {actors.last_name: "DiCaprio"]} )
Comparaison de la structure des requêtes entre SQL/MongoDB
Tables/Collections
CREATE TABLE
SQL | MongoDB |
---|---|
CREATE TABLE people (id MEDIUMINT NOT NULL AUTO_INCREMENT, user_id Varchar(30),\ age Number, status char(1), PRIMARY KEY (id)) | db.people.insertOne( {user_id: "abc123", age: 55, status: "A"} ) ou simplement db.createCollection("people") |
DROP TABLE
SQL | MongoDB |
---|---|
DROP TABLE people | db.people.drop() |
ALTER TABLE
SQL | MongoDB |
---|---|
ALTER TABLE people ADD join_date DATETIME | db.people.updateMany( { },{ $set: { join_date: new Date() } } ) |
ALTER TABLE people DROP COLUMN join_date | db.people.updateMany( { },{ $unset: { "join_date": "" } } ) |
CREATE INDEX
SQL | MongoDB |
---|---|
CREATE INDEX idx_user_id_asc ON people(user_id) | db.people.createIndex( { user_id: 1 } ) |
CREATE INDEX idx_user_id_asc_age_desc ON people(user_id, age DESC) | db.people.createIndex( { user_id: 1, age: -1 } ) |
Rows/documents
INSERT
SQL | MongoDB |
---|---|
INSERT INTO people(user_id, age, status) VALUES ("bcd001", 45, "A") | db.people.insertOne({ user_id: "bcd001", age: 45, status: "A" }) |
SELECT
SQL | MongoDB |
---|---|
SELECT * FROM people | db.people.find() |
SELECT id, user_id, status FROM people | db.people.find( { },{ user_id: 1, status: 1 } ) |
SELECT user_id, status FROM people | db.people.find( { },{ user_id: 1, status: 1, _id: 0 } ) |
SELECT * FROM people WHERE status = "A" | db.people.find( { status: "A" } ) |
SELECT user_id, status FROM people WHERE status = "A" | db.people.find( { status: "A" },{ user_id: 1, status:1, _id: 0 } ) |
SELECT * FROM people WHERE status != "A" | db.people.find( { status: { $ne: "A" } } ) |
SELECT * FROM people WHERE status = "A" AND age = 50 | db.people.find( { status: "A", age: 50 } ) |
SELECT * FROM people WHERE status = "A" OR age = 50 | db.people.find( { $or: [ { status: "A" } , { age: 50 } ] } ) |
SELECT * FROM people WHERE age > 25 | db.people.find( { age: { $gt: 25 } } ) |
SELECT * FROM people WHERE age < 25 | db.people.find( { age: { $lt: 25 } } ) |
SELECT * FROM people WHERE age > 25 AND age <= 50 | db.people.find( { age: { $gt: 25, $lte: 50 } } ) |
SELECT * FROM people WHERE status = "A" ORDER BY user_id ASC | db.people.find( { status: "A" } ).sort( { user_id: 1 } ) |
SELECT * FROM people WHERE status = "A" ORDER BY user_id DESC | db.people.find( { status: "A" } ).sort( { user_id: -1 } ) |
SELECT * FROM people WHERE user_id like "bc%" | db.people.find( { user_id: /^bc/ } ) ou db.people.find( { user_id: { $regex: ^bc/ } } ) |
SELECT * FROM people WHERE user_id like "%bc%" | db.people.find( { user_id: /bc/ } ) ou db.people.find( { user_id: { $regex: /bc/ } } ) |
SELECT COUNT(*) FROM people | db.people.count() ou db.people.find().count() |
SELECT COUNT(user_id) FROM people | db.people.count( { user_id: { $exists: true } } ) ou db.people.find( { user_id: { $exists: true } } ).count() |
SELECT COUNT(*) FROM people WHERE age > 30 | db.people.count( { age: { $gt: 30 } } ) ou db.people.find( { age: { $gt: 30 } } ).count() |
SELECT DISTINCT(status) FROM people | db.people.distinct( "status" ) |
SELECT * FROM people LIMIT 1 | db.people.findOne() ou db.people.find().limit(1) |
SELECT * FROM people LIMIT 5 SKIP 10 | db.people.find().limit(5).skip(10) |
EXPLAIN SELECT
SQL | MongoDB |
---|---|
EXPLAIN SELECT * FROM people WHERE status = "A" | db.people.find( { status: "A" } ).explain() |
UPDATE
SQL | MongoDB |
---|---|
UPDATE people SET status = "C" WHERE age > 25 | db.people.updateMany( { age: { $gt: 25 } } , { $set: { status: "C" } } ) |
UPDATE people SET age = age + 3 WHERE status = "A" | db.people.updateMany( { status: "A" } , { $inc: { age: 3 } } ) |
DELETE FROM
SQL | MongoDB |
---|---|
DELETE FROM people WHERE status = "D" | db.people.deleteMany( { status: "D" } ) |
DELETE FROM people | db.people.deleteMany({}) |
LAB #1 - Utilisation de requêtes de base
Création d'une collection
Commencez par créer une collection nommé Movies qui enregistre des informations sur des films :
test>db.createCollection("movies") { "ok" : 1 } test>
Création de documents
Créez maintenant les documents de la collection :
test>db.movies.insert({ "_id" : "movie:1", "titre" : "Batman", "année" : 1989, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" } ] }) WriteResult({ "nInserted" : 1 }) test>db.movies.insert({ "_id" : "movie:2", "titre" : "Beetlejuice", "année" : 1988, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" }, { "prénom" : "Geena", "nom" : "Davis" } ] }) WriteResult({ "nInserted" : 1 }) test>db.movies.insert({ "_id" : "movie:3", "titre" : "Jurassik Park", "réalisateur" : { "prénom" : "Steven", "nom" : "Spielberg" }, "année" : 1990, "acteurs" : [ { "prénom" : "Sam", "nom" : "Neil" }, { "prénom" : "Laura", "nom" : "Dern" } ] }) WriteResult({ "nInserted" : 1 }) test>db.movies.insert({ "_id" : "movie:4", "titre" : "Avengers", "année" : 2012 }) WriteResult({ "nInserted" : 1 }) test>db.movies.insert({ "_id" : "movie:5", "titre" : "Hobbit", "année" : 2012 }) WriteResult({ "nInserted" : 1 }) test>
Important - Notez que vous avez rentré 2 fois le nom et prénom du champ acteurs pour les 2 premiers documents crées.
Recherche de documents
Utilisez maintenant la commande find pour vérifier que les 5 documents ont bien été crées dans la collection movies :
test>db.movies.find() { "_id" : "movie:1", "titre" : "Batman", "année" : 1989, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" } ] } { "_id" : "movie:2", "titre" : "Beetlejuice", "année" : 1988, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" }, { "prénom" : "Geena", "nom" : "Davis" } ] } { "_id" : "movie:3", "titre" : "Jurassik Park", "réalisateur" : { "prénom" : "Steven", "nom" : "Spielberg" }, "année" : 1990, "acteurs" : [ { "prénom" : "Sam", "nom" : "Neil" }, { "prénom" : "Laura", "nom" : "Dern" } ] } { "_id" : "movie:4", "titre" : "Avengers", "année" : 2012 } { "_id" : "movie:5", "titre" : "Hobbit", "année" : 2012 } test>
Modifiez ensuite le document ayant pour _id : movie 3) en utilisant la commande update :
test>db.movies.update({"_id": "movie:3"}, {$set: {titre: "le parc des dinosaures"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) test>
Important - Notez que le retour indique la réussite de l'oprération de mise à jour - “nModified” : 1.
Vérifiez que le champ a bien été modifié dans le document en consultant la collection movies :
test>db.movies.find() { "_id" : "movie:1", "titre" : "Batman", "année" : 1989, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" } ] } { "_id" : "movie:2", "titre" : "Beetlejuice", "année" : 1988, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" }, { "prénom" : "Geena", "nom" : "Davis" } ] } { "_id" : "movie:3", "titre" : "le parc des dinosaures", "réalisateur" : { "prénom" : "Steven", "nom" : "Spielberg" }, "année" : 1990, "acteurs" : [ { "prénom" : "Sam", "nom" : "Neil" }, { "prénom" : "Laura", "nom" : "Dern" } ] } { "_id" : "movie:4", "titre" : "Avengers", "année" : 2012 } { "_id" : "movie:5", "titre" : "Hobbit", "année" : 2012 } test>
Important - Notez que le titre du film ayant pour “_id” : “movie:3” a bien été modifié.
Affichez maintenant les films n'ayant pas de réalisateur :
test>db.movies.find({"réalisateur": null}) { "_id" : "movie:1", "titre" : "Batman", "année" : 1989, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" } ] } { "_id" : "movie:2", "titre" : "Beetlejuice", "année" : 1988, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" }, { "prénom" : "Geena", "nom" : "Davis" } ] } { "_id" : "movie:4", "titre" : "Avengers", "année" : 2012 } { "_id" : "movie:5", "titre" : "Hobbit", "année" : 2012 } test>
Suppression d'un document
Supprimez le film dont le titre est “Batman” :
test>db.movies.remove({"titre": "Batman"}) WriteResult({ "nRemoved" : 1 }) test>
Constatez le résultat de la requête :
test>db.movies.find() { "_id" : "movie:2", "titre" : "Beetlejuice", "année" : 1988, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" }, { "prénom" : "Geena", "nom" : "Davis" } ] } { "_id" : "movie:3", "titre" : "le parc des dinosaures", "réalisateur" : { "prénom" : "Steven", "nom" : "Spielberg" }, "année" : 1990, "acteurs" : [ { "prénom" : "Sam", "nom" : "Neil" }, { "prénom" : "Laura", "nom" : "Dern" } ] } { "_id" : "movie:4", "titre" : "Avengers", "année" : 2012 } { "_id" : "movie:5", "titre" : "Hobbit", "année" : 2012 } test>
Supprimez maintenant les films ayant “année”: 2012 :
test>db.movies.remove({"année": 2012}) WriteResult({ "nRemoved" : 2 }) test>db.movies.find() { "_id" : "movie:2", "titre" : "Beetlejuice", "année" : 1988, "acteurs" : [ { "prénom" : "Michael", "nom" : "Keaton" }, { "prénom" : "Geena", "nom" : "Davis" } ] } { "_id" : "movie:3", "titre" : "le parc des dinosaures", "réalisateur" : { "prénom" : "Steven", "nom" : "Spielberg" }, "année" : 1990, "acteurs" : [ { "prénom" : "Sam", "nom" : "Neil" }, { "prénom" : "Laura", "nom" : "Dern" } ] }
Important - Notez la suppression de deux documents : “_id” : “movie:4” et “_id” : “movie:5”.
LAB #2 - Rechercher, filtrer et trier
La Requête find()
Connectez-vous à MongoDB en utilisant le client mongo :
[trainee@centos7 ~]$ su - Mot de passe : fenestros Dernière connexion : lundi 18 septembre 2017 à 13:39:03 CEST sur pts/0 [root@centos7 ~]# mongo MongoDB shell version: 3.2.16 connecting to: test Server has startup warnings: 2017-09-18T13:46:09.416+0200 I CONTROL [initandlisten] 2017-09-18T13:46:09.416+0200 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 4096 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files. test>
Commencez par créer une base de données appelée find :
test>use find switched to db find find>
Critères de recherche
En sachant que le client mongo interprète du JavaScript, créez 100 000 documents dans la base de données find dans une collection appelée products :
find>for(i=1; i<=100000; i++){var tenthousand = i%10000; var thousand = i%1000; var hundred = i%100; db.products.insert({counter:i, tenthousand:tenthousand, thousand:thousand, hundred:hundred })} WriteResult({ "nInserted" : 1 })
Saisissez maintenant la commande db.products.find() :
find>db.products.find() { "_id" : ObjectId("59c0fb1a3b6221e3d36169a6"), "counter" : 1, "tenthousand" : 1, "thousand" : 1, "hundred" : 1 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169a7"), "counter" : 2, "tenthousand" : 2, "thousand" : 2, "hundred" : 2 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169a8"), "counter" : 3, "tenthousand" : 3, "thousand" : 3, "hundred" : 3 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169a9"), "counter" : 4, "tenthousand" : 4, "thousand" : 4, "hundred" : 4 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169aa"), "counter" : 5, "tenthousand" : 5, "thousand" : 5, "hundred" : 5 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169ab"), "counter" : 6, "tenthousand" : 6, "thousand" : 6, "hundred" : 6 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169ac"), "counter" : 7, "tenthousand" : 7, "thousand" : 7, "hundred" : 7 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169ad"), "counter" : 8, "tenthousand" : 8, "thousand" : 8, "hundred" : 8 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169ae"), "counter" : 9, "tenthousand" : 9, "thousand" : 9, "hundred" : 9 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169af"), "counter" : 10, "tenthousand" : 10, "thousand" : 10, "hundred" : 10 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b0"), "counter" : 11, "tenthousand" : 11, "thousand" : 11, "hundred" : 11 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b1"), "counter" : 12, "tenthousand" : 12, "thousand" : 12, "hundred" : 12 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b2"), "counter" : 13, "tenthousand" : 13, "thousand" : 13, "hundred" : 13 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b3"), "counter" : 14, "tenthousand" : 14, "thousand" : 14, "hundred" : 14 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b4"), "counter" : 15, "tenthousand" : 15, "thousand" : 15, "hundred" : 15 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b5"), "counter" : 16, "tenthousand" : 16, "thousand" : 16, "hundred" : 16 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b6"), "counter" : 17, "tenthousand" : 17, "thousand" : 17, "hundred" : 17 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b7"), "counter" : 18, "tenthousand" : 18, "thousand" : 18, "hundred" : 18 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b8"), "counter" : 19, "tenthousand" : 19, "thousand" : 19, "hundred" : 19 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169b9"), "counter" : 20, "tenthousand" : 20, "thousand" : 20, "hundred" : 20 } Type "it" for more find>
Notez l'instruction Type “it” for more :
find>it { "_id" : ObjectId("59c0fb1a3b6221e3d36169ba"), "counter" : 21, "tenthousand" : 21, "thousand" : 21, "hundred" : 21 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169bb"), "counter" : 22, "tenthousand" : 22, "thousand" : 22, "hundred" : 22 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169bc"), "counter" : 23, "tenthousand" : 23, "thousand" : 23, "hundred" : 23 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169bd"), "counter" : 24, "tenthousand" : 24, "thousand" : 24, "hundred" : 24 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169be"), "counter" : 25, "tenthousand" : 25, "thousand" : 25, "hundred" : 25 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169bf"), "counter" : 26, "tenthousand" : 26, "thousand" : 26, "hundred" : 26 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c0"), "counter" : 27, "tenthousand" : 27, "thousand" : 27, "hundred" : 27 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c1"), "counter" : 28, "tenthousand" : 28, "thousand" : 28, "hundred" : 28 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c2"), "counter" : 29, "tenthousand" : 29, "thousand" : 29, "hundred" : 29 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c3"), "counter" : 30, "tenthousand" : 30, "thousand" : 30, "hundred" : 30 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c4"), "counter" : 31, "tenthousand" : 31, "thousand" : 31, "hundred" : 31 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c5"), "counter" : 32, "tenthousand" : 32, "thousand" : 32, "hundred" : 32 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c6"), "counter" : 33, "tenthousand" : 33, "thousand" : 33, "hundred" : 33 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c7"), "counter" : 34, "tenthousand" : 34, "thousand" : 34, "hundred" : 34 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c8"), "counter" : 35, "tenthousand" : 35, "thousand" : 35, "hundred" : 35 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169c9"), "counter" : 36, "tenthousand" : 36, "thousand" : 36, "hundred" : 36 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169ca"), "counter" : 37, "tenthousand" : 37, "thousand" : 37, "hundred" : 37 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169cb"), "counter" : 38, "tenthousand" : 38, "thousand" : 38, "hundred" : 38 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169cc"), "counter" : 39, "tenthousand" : 39, "thousand" : 39, "hundred" : 39 } { "_id" : ObjectId("59c0fb1a3b6221e3d36169cd"), "counter" : 40, "tenthousand" : 40, "thousand" : 40, "hundred" : 40 } Type "it" for more find>
Important - Bien que pratique, il faudrait taper la commande it un grand nombre de fois pour atteindre le document 90 000 !
Tapez maintenat la commande db.products.find({tenthousand:9999}) :
find>db.products.find({tenthousand:9999}) { "_id" : ObjectId("59c0fb2d3b6221e3d36190b4"), "counter" : 9999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fb403b6221e3d361b7c4"), "counter" : 19999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fb533b6221e3d361ded4"), "counter" : 29999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fb663b6221e3d36205e4"), "counter" : 39999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fb793b6221e3d3622cf4"), "counter" : 49999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fb8e3b6221e3d3625404"), "counter" : 59999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fba13b6221e3d3627b14"), "counter" : 69999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fbb43b6221e3d362a224"), "counter" : 79999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fbc93b6221e3d362c934"), "counter" : 89999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } { "_id" : ObjectId("59c0fbdc3b6221e3d362f044"), "counter" : 99999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } find>
Important - Vous obtenez les documents qui correspondent à tenthousand = 9999.
Précisez maintenant un deuxième critère de recherche :
find>db.products.find({counter:19999, tenthousand:9999}) { "_id" : ObjectId("59c0fb403b6221e3d361b7c4"), "counter" : 19999, "tenthousand" : 9999, "thousand" : 999, "hundred" : 99 } find>
Important - Vous obtenez un seul document où counter=19999 et tenthousand=9999.
Pour connaître le nombre de documents retournés lors d'une recherche spécifique, utilisez la commande count() :
find>db.products.find({thousand:289, hundred:89}) { "_id" : ObjectId("59c0fb1a3b6221e3d3616ac6"), "counter" : 289, "tenthousand" : 289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb1d3b6221e3d3616eae"), "counter" : 1289, "tenthousand" : 1289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb1e3b6221e3d3617296"), "counter" : 2289, "tenthousand" : 2289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb203b6221e3d361767e"), "counter" : 3289, "tenthousand" : 3289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb223b6221e3d3617a66"), "counter" : 4289, "tenthousand" : 4289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb243b6221e3d3617e4e"), "counter" : 5289, "tenthousand" : 5289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb263b6221e3d3618236"), "counter" : 6289, "tenthousand" : 6289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb283b6221e3d361861e"), "counter" : 7289, "tenthousand" : 7289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb2a3b6221e3d3618a06"), "counter" : 8289, "tenthousand" : 8289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb2c3b6221e3d3618dee"), "counter" : 9289, "tenthousand" : 9289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb2e3b6221e3d36191d6"), "counter" : 10289, "tenthousand" : 289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb2f3b6221e3d36195be"), "counter" : 11289, "tenthousand" : 1289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb313b6221e3d36199a6"), "counter" : 12289, "tenthousand" : 2289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb333b6221e3d3619d8e"), "counter" : 13289, "tenthousand" : 3289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb353b6221e3d361a176"), "counter" : 14289, "tenthousand" : 4289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb373b6221e3d361a55e"), "counter" : 15289, "tenthousand" : 5289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb393b6221e3d361a946"), "counter" : 16289, "tenthousand" : 6289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb3b3b6221e3d361ad2e"), "counter" : 17289, "tenthousand" : 7289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb3d3b6221e3d361b116"), "counter" : 18289, "tenthousand" : 8289, "thousand" : 289, "hundred" : 89 } { "_id" : ObjectId("59c0fb3f3b6221e3d361b4fe"), "counter" : 19289, "tenthousand" : 9289, "thousand" : 289, "hundred" : 89 } Type "it" for more find>db.products.find({thousand:289, hundred:89}).count() 100 find>
Important - Notez qu'il existe 100 documents correspondant à notre critère ({thousand:289, hundred:89}).
Utiliser des Opérandes
Il est possilible d'utiliser des opérandes avec la requête find() :
Opérande | Description |
---|---|
$gt | Supérieur à |
$gte | Supérieur ou égal à |
$lt | Inférieur à |
$lte | Inférieur ou égal à |
Important - Les 4 opérandes ci-dessus fonctionnent pour des nombres et des chaines de caractères. Dans le cas des chaines de caractères, l'ordre appliqué est l'ordre alphabétique.
Par exemple le nombre de documents qui ont pour la valeur thousand supérieure ou égale à 525 et la valeur hundred inférieure à 90 :
find>db.products.find({thousand:{$gte:525}, hundred:{$lt:90}}).count() 42500 find>
Filtrer les champs
Saisissez la requête db.products.find({tenthousand: 525}) :
find>db.products.find({tenthousand: 525}) { "_id" : ObjectId("59c0fb1b3b6221e3d3616bb2"), "counter" : 525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fb2e3b6221e3d36192c2"), "counter" : 10525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fb413b6221e3d361b9d2"), "counter" : 20525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fb543b6221e3d361e0e2"), "counter" : 30525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fb673b6221e3d36207f2"), "counter" : 40525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fb7a3b6221e3d3622f02"), "counter" : 50525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fb8f3b6221e3d3625612"), "counter" : 60525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fba23b6221e3d3627d22"), "counter" : 70525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fbb53b6221e3d362a432"), "counter" : 80525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } { "_id" : ObjectId("59c0fbca3b6221e3d362cb42"), "counter" : 90525, "tenthousand" : 525, "thousand" : 525, "hundred" : 25 } find>
Ajoutez maintenant un deuxième paramètre destiné à filtrer les champs retournés par la requête :
find>db.products.find({tenthousand: 525} , {counter:1}) { "_id" : ObjectId("59c0fb1b3b6221e3d3616bb2"), "counter" : 525 } { "_id" : ObjectId("59c0fb2e3b6221e3d36192c2"), "counter" : 10525 } { "_id" : ObjectId("59c0fb413b6221e3d361b9d2"), "counter" : 20525 } { "_id" : ObjectId("59c0fb543b6221e3d361e0e2"), "counter" : 30525 } { "_id" : ObjectId("59c0fb673b6221e3d36207f2"), "counter" : 40525 } { "_id" : ObjectId("59c0fb7a3b6221e3d3622f02"), "counter" : 50525 } { "_id" : ObjectId("59c0fb8f3b6221e3d3625612"), "counter" : 60525 } { "_id" : ObjectId("59c0fba23b6221e3d3627d22"), "counter" : 70525 } { "_id" : ObjectId("59c0fbb53b6221e3d362a432"), "counter" : 80525 } { "_id" : ObjectId("59c0fbca3b6221e3d362cb42"), "counter" : 90525 } find>
Important - Notez que vous n'avez plus que les champs _id et counter dans les résultats. Le champs _id est systématiquement renvoyé sauf quand il est explicitement indiqué le contraire dans la requête. counter est renvoyé parce que dans le second paramètre se trouve la valeur 1.
Saisissez donc la requête suivante qui indique que celle-ci ne doit pas retournée le champs _id :
find>db.products.find({tenthousand: 525} , {_id:0, counter:1}) { "counter" : 525 } { "counter" : 10525 } { "counter" : 20525 } { "counter" : 30525 } { "counter" : 40525 } { "counter" : 50525 } { "counter" : 60525 } { "counter" : 70525 } { "counter" : 80525 } { "counter" : 90525 } find>
Trier
Saissisez la requête suivante :
find>db.products.find({thousand : {$in: [500, 600, 700]}}) { "_id" : ObjectId("59c0fb1b3b6221e3d3616b99"), "counter" : 500, "tenthousand" : 500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb1b3b6221e3d3616bfd"), "counter" : 600, "tenthousand" : 600, "thousand" : 600, "hundred" : 0 } { "_id" : ObjectId("59c0fb1b3b6221e3d3616c61"), "counter" : 700, "tenthousand" : 700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb1d3b6221e3d3616f81"), "counter" : 1500, "tenthousand" : 1500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb1d3b6221e3d3616fe5"), "counter" : 1600, "tenthousand" : 1600, "thousand" : 600, "hundred" : 0 } { "_id" : ObjectId("59c0fb1d3b6221e3d3617049"), "counter" : 1700, "tenthousand" : 1700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb1f3b6221e3d3617369"), "counter" : 2500, "tenthousand" : 2500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb1f3b6221e3d36173cd"), "counter" : 2600, "tenthousand" : 2600, "thousand" : 600, "hundred" : 0 } { "_id" : ObjectId("59c0fb1f3b6221e3d3617431"), "counter" : 2700, "tenthousand" : 2700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb213b6221e3d3617751"), "counter" : 3500, "tenthousand" : 3500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb213b6221e3d36177b5"), "counter" : 3600, "tenthousand" : 3600, "thousand" : 600, "hundred" : 0 } { "_id" : ObjectId("59c0fb213b6221e3d3617819"), "counter" : 3700, "tenthousand" : 3700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb233b6221e3d3617b39"), "counter" : 4500, "tenthousand" : 4500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb233b6221e3d3617b9d"), "counter" : 4600, "tenthousand" : 4600, "thousand" : 600, "hundred" : 0 } { "_id" : ObjectId("59c0fb233b6221e3d3617c01"), "counter" : 4700, "tenthousand" : 4700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb253b6221e3d3617f21"), "counter" : 5500, "tenthousand" : 5500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb253b6221e3d3617f85"), "counter" : 5600, "tenthousand" : 5600, "thousand" : 600, "hundred" : 0 } { "_id" : ObjectId("59c0fb253b6221e3d3617fe9"), "counter" : 5700, "tenthousand" : 5700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb263b6221e3d3618309"), "counter" : 6500, "tenthousand" : 6500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb273b6221e3d361836d"), "counter" : 6600, "tenthousand" : 6600, "thousand" : 600, "hundred" : 0 } Type "it" for more find>
Important - Notez que le résultat démontre une alternance des valeurs de thousand, alternativement 500, 600 et 700.
Triez maintenant les résultats sur la valeur de thousand dans le sens croissant :
find>db.products.find({thousand : {$in: [500, 600, 700]}}).sort({thousand:1}) { "_id" : ObjectId("59c0fb1b3b6221e3d3616b99"), "counter" : 500, "tenthousand" : 500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb1d3b6221e3d3616f81"), "counter" : 1500, "tenthousand" : 1500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb1f3b6221e3d3617369"), "counter" : 2500, "tenthousand" : 2500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb213b6221e3d3617751"), "counter" : 3500, "tenthousand" : 3500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb233b6221e3d3617b39"), "counter" : 4500, "tenthousand" : 4500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb253b6221e3d3617f21"), "counter" : 5500, "tenthousand" : 5500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb263b6221e3d3618309"), "counter" : 6500, "tenthousand" : 6500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb283b6221e3d36186f1"), "counter" : 7500, "tenthousand" : 7500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb2a3b6221e3d3618ad9"), "counter" : 8500, "tenthousand" : 8500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb2c3b6221e3d3618ec1"), "counter" : 9500, "tenthousand" : 9500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb2e3b6221e3d36192a9"), "counter" : 10500, "tenthousand" : 500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb303b6221e3d3619691"), "counter" : 11500, "tenthousand" : 1500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb323b6221e3d3619a79"), "counter" : 12500, "tenthousand" : 2500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb343b6221e3d3619e61"), "counter" : 13500, "tenthousand" : 3500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb363b6221e3d361a249"), "counter" : 14500, "tenthousand" : 4500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb373b6221e3d361a631"), "counter" : 15500, "tenthousand" : 5500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb393b6221e3d361aa19"), "counter" : 16500, "tenthousand" : 6500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb3b3b6221e3d361ae01"), "counter" : 17500, "tenthousand" : 7500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb3d3b6221e3d361b1e9"), "counter" : 18500, "tenthousand" : 8500, "thousand" : 500, "hundred" : 0 } { "_id" : ObjectId("59c0fb3f3b6221e3d361b5d1"), "counter" : 19500, "tenthousand" : 9500, "thousand" : 500, "hundred" : 0 } Type "it" for more find>
Dernièrement, triez dans le sens décroissant :
find>db.products.find({thousand : {$in: [500, 600, 700]}}).sort({thousand:-1}) { "_id" : ObjectId("59c0fb1b3b6221e3d3616c61"), "counter" : 700, "tenthousand" : 700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb1d3b6221e3d3617049"), "counter" : 1700, "tenthousand" : 1700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb1f3b6221e3d3617431"), "counter" : 2700, "tenthousand" : 2700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb213b6221e3d3617819"), "counter" : 3700, "tenthousand" : 3700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb233b6221e3d3617c01"), "counter" : 4700, "tenthousand" : 4700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb253b6221e3d3617fe9"), "counter" : 5700, "tenthousand" : 5700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb273b6221e3d36183d1"), "counter" : 6700, "tenthousand" : 6700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb293b6221e3d36187b9"), "counter" : 7700, "tenthousand" : 7700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb2b3b6221e3d3618ba1"), "counter" : 8700, "tenthousand" : 8700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb2d3b6221e3d3618f89"), "counter" : 9700, "tenthousand" : 9700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb2e3b6221e3d3619371"), "counter" : 10700, "tenthousand" : 700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb303b6221e3d3619759"), "counter" : 11700, "tenthousand" : 1700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb323b6221e3d3619b41"), "counter" : 12700, "tenthousand" : 2700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb343b6221e3d3619f29"), "counter" : 13700, "tenthousand" : 3700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb363b6221e3d361a311"), "counter" : 14700, "tenthousand" : 4700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb383b6221e3d361a6f9"), "counter" : 15700, "tenthousand" : 5700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb3a3b6221e3d361aae1"), "counter" : 16700, "tenthousand" : 6700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb3c3b6221e3d361aec9"), "counter" : 17700, "tenthousand" : 7700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb3e3b6221e3d361b2b1"), "counter" : 18700, "tenthousand" : 8700, "thousand" : 700, "hundred" : 0 } { "_id" : ObjectId("59c0fb3f3b6221e3d361b699"), "counter" : 19700, "tenthousand" : 9700, "thousand" : 700, "hundred" : 0 } Type "it" for more find>
LAB #3 - Requêtes sur la base movies
Préparation
Sortez du client mongo, puis télécharger à partir de la section Fichiers de ce cours le fichier au format JSON dont nous aurons besoin pour ce LAB :
- movies.json
- ce fichier contient la liste de films complets comprenant tous les noms et prénoms des artistes, répétés à chaque occurrence.
Création de base de données
Connectez-vous à MongoDB avec le client mongo et créez une base de données movies contenant une collection movies,
[root@centos7 ~]# mongo MongoDB shell version: 3.2.16 connecting to: test Server has startup warnings: 2017-09-19T11:51:43.992+0200 I CONTROL [initandlisten] 2017-09-19T11:51:43.992+0200 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 4096 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files. test>use movies switched to db movies movies>db.createCollection("movies") { "ok" : 1 } movies>exit bye
Importer les données
Utilisez maintenant la commande mongoimport pour importer le fichier dans MongoDB :
[root@centos7 ~]# mongoimport -d movies -c movies --file movies.json --jsonArray 2017-09-20T11:19:44.012+0200 connected to: localhost 2017-09-20T11:19:44.122+0200 imported 88 documents
Important - Notez que l’argument jsonArray indique à mongoimport qu’il s’agit d’un tableau d’objets à créer individuellement, et pas d’un unique document JSON.
Re-connectez-vous à MongoDB en utilisant le client mongo :
[root@centos7 ~]# mongo MongoDB shell version: 3.2.16 connecting to: test Server has startup warnings: 2017-09-19T11:51:43.992+0200 I CONTROL [initandlisten] 2017-09-19T11:51:43.992+0200 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 4096 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files. test>
En utilisant la base de données movies, vérifiez que vous pouvez trouver les 88 documents :
movies>db.movies.count () 88
Exercices
Trouvez maintenant les informations suivantes :
- tous les titres,
- le résumé de Spider-Man,
- le metteur en scène de Gladiator,
- les titres des films avec Kirsten Dunst,
- les films ayant un résumé,
- les films qui ne sont ni des drames ni des comédies,
- les titres des films et les noms des acteurs,
- les films où Clint Eastwood est acteur mais pas réalisateur.
Corrigés
Tous les titres
movies>db.movies.find({}, {"title": 1}) { "_id" : "movie:1", "title" : "Vertigo" } { "_id" : "movie:2", "title" : "Alien" } { "_id" : "movie:3", "title" : "Titanic" } { "_id" : "movie:4", "title" : "Sacrifice" } { "_id" : "movie:5", "title" : "Volte/Face" } { "_id" : "movie:6", "title" : "Sleepy Hollow" } { "_id" : "movie:7", "title" : "American Beauty" } { "_id" : "movie:8", "title" : "Impitoyable" } { "_id" : "movie:9", "title" : "Gladiator" } { "_id" : "movie:10", "title" : "Blade Runner" } { "_id" : "movie:11", "title" : "Piège de cristal" } { "_id" : "movie:12", "title" : "58 minutes pour vivre" } { "_id" : "movie:13", "title" : "Van Gogh" } { "_id" : "movie:14", "title" : "Seven" } { "_id" : "movie:15", "title" : "Twelve Monkeys" } { "_id" : "movie:16", "title" : "Le last_name de la rose" } { "_id" : "movie:17", "title" : "Pulp fiction" } { "_id" : "movie:18", "title" : "Mary à tout prix" } { "_id" : "movie:19", "title" : "Terminator" } { "_id" : "movie:20", "title" : "Les dents de la mer" } Type "it" for more movies>
Le résumé de Spider-Man
movies>db.movies.find({"title": "Spider-Man"}, {"summary": 1}) { "_id" : "movie:47", "summary" : "Orphelin, Peter Parker est élevé par sa tante May et son oncle Ben dans le quartier Queens de New York. Tout en poursuivant ses études à l'université, il trouve un emploi de photographe au journal Daily Bugle. Il partage son appartement avec Harry Osborn, son meilleur ami, et rêve de séduire la belle Mary Jane.Cependant, après avoir été mordu par une araignée génétiquement modifiée, Peter voit son agilité et sa force s'accroître et se découvre des pouvoirs surnaturels. Devenu Spider-Man, il décide d'utiliser ses nouvelles capacités au service du bien.Au même moment, le père de Harry, le richissime industriel Norman Osborn, est victime d'un accident chimique qui a démesurément augmenté ses facultés intellectuelles et sa force, mais l'a rendu fou. Il est devenu le Bouffon Vert, une créature démoniaque qui menace la ville. Entre lui et Spider-Man, une lutte sans merci s'engage." }
Le metteur en scène de Gladiator
movies>db.movies.find({"title": "Gladiator"}, {"director": 1}) { "_id" : "movie:9", "director" : { "_id" : "artist:4", "last_name" : "Scott", "first_name" : "Ridley", "birth_date" : "1937" } }
Les titres des films avec Kirsten Dunst
movies>db.movies.find({"actors.last_name": "Dunst"}, {"title": 1}) { "_id" : "movie:67", "title" : "Marie Antoinette" }
Les films ayant un résumé
movies>db.movies.find({"summary": {$exists: true}}, {"title": 1}) { "_id" : "movie:1", "title" : "Vertigo" } { "_id" : "movie:2", "title" : "Alien" } { "_id" : "movie:3", "title" : "Titanic" } { "_id" : "movie:4", "title" : "Sacrifice" } { "_id" : "movie:5", "title" : "Volte/Face" } { "_id" : "movie:6", "title" : "Sleepy Hollow" } { "_id" : "movie:7", "title" : "American Beauty" } { "_id" : "movie:8", "title" : "Impitoyable" } { "_id" : "movie:9", "title" : "Gladiator" } { "_id" : "movie:10", "title" : "Blade Runner" } { "_id" : "movie:11", "title" : "Piège de cristal" } { "_id" : "movie:12", "title" : "58 minutes pour vivre" } { "_id" : "movie:13", "title" : "Van Gogh" } { "_id" : "movie:14", "title" : "Seven" } { "_id" : "movie:15", "title" : "Twelve Monkeys" } { "_id" : "movie:16", "title" : "Le last_name de la rose" } { "_id" : "movie:17", "title" : "Pulp fiction" } { "_id" : "movie:18", "title" : "Mary à tout prix" } { "_id" : "movie:19", "title" : "Terminator" } { "_id" : "movie:20", "title" : "Les dents de la mer" } Type "it" for more
Les films qui ne sont ni des drames ni des comédies
movies>db.movies.find({"genre": {$nin: ["Drame", "Comédie"]}}, {"title": 1, "genre": 1}) { "_id" : "movie:1", "title" : "Vertigo", "genre" : "drama" } { "_id" : "movie:2", "title" : "Alien", "genre" : "Science-fiction" } { "_id" : "movie:3", "title" : "Titanic", "genre" : "drama" } { "_id" : "movie:4", "title" : "Sacrifice", "genre" : "drama" } { "_id" : "movie:5", "title" : "Volte/Face", "genre" : "Action" } { "_id" : "movie:6", "title" : "Sleepy Hollow", "genre" : "Fantastique" } { "_id" : "movie:8", "title" : "Impitoyable", "genre" : "Western" } { "_id" : "movie:9", "title" : "Gladiator", "genre" : "drama" } { "_id" : "movie:10", "title" : "Blade Runner", "genre" : "Action" } { "_id" : "movie:11", "title" : "Piège de cristal", "genre" : "Action" } { "_id" : "movie:12", "title" : "58 minutes pour vivre", "genre" : "Action" } { "_id" : "movie:13", "title" : "Van Gogh", "genre" : "drama" } { "_id" : "movie:14", "title" : "Seven", "genre" : "crime" } { "_id" : "movie:15", "title" : "Twelve Monkeys", "genre" : "Science-fiction" } { "_id" : "movie:16", "title" : "Le last_name de la rose", "genre" : "crime" } { "_id" : "movie:17", "title" : "Pulp fiction", "genre" : "Action" } { "_id" : "movie:19", "title" : "Terminator", "genre" : "Science-fiction" } { "_id" : "movie:20", "title" : "Les dents de la mer", "genre" : "Horreur" } { "_id" : "movie:21", "title" : "Le silence des agneaux", "genre" : "crime" } { "_id" : "movie:22", "title" : "Godzilla", "genre" : "Action" } Type "it" for more
Les titres des films et les noms des acteurs
movies>db.movies.find({}, {"title": 1, "actors.first_name": 1, "actors.last_name": 1}) { "_id" : "movie:1", "title" : "Vertigo", "actors" : [ { "first_name" : "James", "last_name" : "Stewart" }, { "first_name" : "Kim", "last_name" : "Novak" }, { "first_name" : "Arthur", "last_name" : "Pierre" } ] } { "_id" : "movie:2", "title" : "Alien", "actors" : [ { "first_name" : "Sigourney", "last_name" : "Weaver" } ] } { "_id" : "movie:3", "title" : "Titanic", "actors" : [ { "first_name" : "Kate", "last_name" : "Winslet" }, { "first_name" : "Leonardo", "last_name" : "DiCaprio" } ] } { "_id" : "movie:4", "title" : "Sacrifice", "actors" : [ ] } { "_id" : "movie:5", "title" : "Volte/Face", "actors" : [ { "first_name" : "John", "last_name" : "Travolta" }, { "first_name" : "Nicolas", "last_name" : "Cage" } ] } { "_id" : "movie:6", "title" : "Sleepy Hollow", "actors" : [ { "first_name" : "Johnny", "last_name" : "Depp" }, { "first_name" : "Christina", "last_name" : "Ricci" }, { "first_name" : "Christopher", "last_name" : "Walken" } ] } { "_id" : "movie:7", "title" : "American Beauty", "actors" : [ { "first_name" : "Kevin", "last_name" : "Spacey" }, { "first_name" : "Anette", "last_name" : "Bening" } ] } { "_id" : "movie:8", "title" : "Impitoyable", "actors" : [ { "first_name" : "Clint", "last_name" : "Eastwood" }, { "first_name" : "Gene", "last_name" : "Hackman" }, { "first_name" : "Morgan", "last_name" : "Freeman" } ] } { "_id" : "movie:9", "title" : "Gladiator", "actors" : [ { "first_name" : "Russell", "last_name" : "Crowe" }, { "first_name" : "Adam", "last_name" : "Baldwin" }, { "first_name" : "Ryan", "last_name" : "ONeal" }, { "first_name" : "Marisa", "last_name" : "Berenson" } ] } { "_id" : "movie:10", "title" : "Blade Runner", "actors" : [ { "first_name" : "Harrison", "last_name" : "Ford" }, { "first_name" : "Rutger", "last_name" : "Hauer" } ] } { "_id" : "movie:11", "title" : "Piège de cristal", "actors" : [ { "first_name" : "Bruce", "last_name" : "Willis" } ] } { "_id" : "movie:12", "title" : "58 minutes pour vivre", "actors" : [ { "first_name" : "Bruce", "last_name" : "Willis" } ] } { "_id" : "movie:13", "title" : "Van Gogh", "actors" : [ { "first_name" : "Jacques", "last_name" : "Dutronc" } ] } { "_id" : "movie:14", "title" : "Seven", "actors" : [ { "first_name" : "Kevin", "last_name" : "Spacey" }, { "first_name" : "Morgan", "last_name" : "Freeman" }, { "first_name" : "Brad", "last_name" : "Pitt" } ] } { "_id" : "movie:15", "title" : "Twelve Monkeys", "actors" : [ { "first_name" : "Bruce", "last_name" : "Willis" } ] } { "_id" : "movie:16", "title" : "Le last_name de la rose", "actors" : [ { "first_name" : "Sean", "last_name" : "Connery" }, { "first_name" : "Christian", "last_name" : "Slater" } ] } { "_id" : "movie:17", "title" : "Pulp fiction", "actors" : [ { "first_name" : "John", "last_name" : "Travolta" }, { "first_name" : "Bruce", "last_name" : "Willis" }, { "first_name" : "Quentin", "last_name" : "Tarantino" }, { "first_name" : "Samuel L.", "last_name" : "Jackson" }, { "first_name" : "Rosanna", "last_name" : "Arquette" }, { "first_name" : "Uma", "last_name" : "Thurman" }, { "first_name" : "Christopher", "last_name" : "Walken" }, { "first_name" : "Harvey", "last_name" : "Keitel" }, { "first_name" : "Tim", "last_name" : "Roth" } ] } { "_id" : "movie:18", "title" : "Mary à tout prix", "actors" : [ { "first_name" : "Cameron", "last_name" : "Diaz" }, { "first_name" : "Mat", "last_name" : "Dillon" } ] } { "_id" : "movie:19", "title" : "Terminator", "actors" : [ { "first_name" : "Arnold", "last_name" : "Schwartzenegger" } ] } { "_id" : "movie:20", "title" : "Les dents de la mer", "actors" : [ { "first_name" : "Roy", "last_name" : "Scheider" }, { "first_name" : "Robert", "last_name" : "Shaw" }, { "first_name" : "Richard", "last_name" : "Dreyfus" } ] } Type "it" for more
Les films où Clint Eastwood est acteur mais pas réalisateur
movies>db.movies.find({"actors.last_name": "Eastwood", "director.last_name": {$ne: "Eastwood"}}, {"title": 1}) { "_id" : "movie:32", "title" : "Le bon, la brute et le truand" }
LAB #4 - Jointures
Préparation
Sortez du client mongo, puis téléchargez à partir de la section Fichiers de ce cours les deux fichiers au format JSON dont nous aurons besoin pour ce LAB :
- movies_ref.json
- ce fichier contient la liste des films avec références, les identifiants des artistes, et impose donc d'effectuer des jointures
- artists.json
- ce fichier contient la liste des artistes.
Création des bases de données
Connectez-vous à MongoDB avec le client mongo et créez une base de données moviesref contenant deux collections movies et artists.
[root@centos7 ~]# mongo MongoDB shell version: 3.2.16 connecting to: test Server has startup warnings: 2017-09-19T11:51:43.992+0200 I CONTROL [initandlisten] 2017-09-19T11:51:43.992+0200 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 4096 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files. movies>use moviesref switched to db moviesref moviesref>db.createCollection("movies") { "ok" : 1 } moviesref>db.createCollection("artists") { "ok" : 1 } moviesref>exit bye
Importer les données
Utilisez maintenant la commande mongoimport pour importer les fichiers dans MongoDB :
[root@centos7 ~]# mongoimport -d moviesref -c movies --file movies-refs.json --jsonArray 2017-09-20T11:19:58.697+0200 connected to: localhost 2017-09-20T11:19:58.721+0200 imported 88 documents [root@centos7 ~]# mongoimport -d moviesref -c artists --file artists.json --jsonArray 2017-09-20T11:20:14.384+0200 connected to: localhost 2017-09-20T11:20:14.405+0200 imported 206 documents
Important - Notez que l’argument jsonArray indique à mongoimport qu’il s’agit d’un tableau d’objets à créer individuellement, et pas d’un unique document JSON.
Re-connectez-vous à MongoDB en utilisant le client mongo :
[root@centos7 ~]# mongo MongoDB shell version: 3.2.16 connecting to: test Server has startup warnings: 2017-09-19T11:51:43.992+0200 I CONTROL [initandlisten] 2017-09-19T11:51:43.992+0200 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 4096 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files. test>use moviesref switched to db moviesref
Effectuer la jointure du côté client
Le serveur MongoDB ne sait pas effectuer de jointures. Pour cette raison celles-ci doivent être mises en place du côté client. Cela revient essentiellement à appliquer l’algorithme de jointures par boucle imbriquées en stockant des données temporaires dans des structures de données sur le client, et en effectuant des échanges réseaux entre le client et le serveur.
La première étape dans la jointure côté client consiste à chercher l’artiste Clint Eastwood et à le stocker dans l’espace mémoire du client :
moviesref>eastwood = db.artists.findOne({"first_name": "Clint", "last_name": "Eastwood"}) { "_id" : "artist:20", "last_name" : "Eastwood", "first_name" : "Clint", "birth_date" : "1930" }
Ensuite il convient d'utiliser cette “variable” pour rechercher dans la collection movies :
moviesref>db.movies.find({"director._id": eastwood['_id']}, {"title": 1}) { "_id" : "movie:8", "title" : "Impitoyable" } { "_id" : "movie:26", "title" : "Les pleins pouvoirs" } { "_id" : "movie:63", "title" : "Million Dollar Baby" }
MapReduce
Définition
Etant donné une collection de documents on applique un traitement en deux phases:
La première phase appelée map
Une fonction est appliquée à chaque document de la collection et produit une valeur placée dans un accumulateur.
La seconde phase appelée reduce
Les valeurs placées dans l’accumulateur sont traitées par une fonction d’agrégation reduce ,produisant une valeur finale.
Un exemple simple peut être vu en considérant la requête SQL suivante :
select count(*) from Collection
Dans ce cas :
- la phase map produit une valeur de 1 et la place dans l'accumulateur pour chaque document dans la collection,
- la phase reduce calcule la somme pour produire un résultat.
En allant un peu plus loins, considérez la requête SQL suivante :
select count(*) from Collection group by annee
Dans ce cas, les valeurs produites par le map sont partionnées en groupes où chaque groupe représente une année. Le map produit donc des paires groupe, valeur ou année, valeur.
Revenons maintenant à notre base de données de films. Notre but est de produire un document par réalisateur contenant la liste des films réalisés par ce réalisateur :
- la phase map : un groupe doit être créé par réalisateur contenant les films réalisés par ce dernier,
- la phase reduce : la création du document final.
Par exemple la phase map est la définition d'une variable mapRealisateur contenant une fonction. Saisissez donc cette commande dans l'interface du client mongo :
movies>var mapRealisateur = function() { ... emit(this.director._id, this.title); ... }; movies>
Important - La fonction contient l'instruction emit qui produit une paire clef:valeur constituée de l'identifiant du réalisateur et du titre du film. Le mot clef this indique le document actuel.
La phase reduce contient une fonction, reduceRealisateur, qui prend deux arguments directorId, l’identifiant du groupe auquel elle s’applique, et la liste des valeurs produites par le map sous forme d'un tableau javascript. Saisissez donc cette commande dans l'interface du client mongo :
movies>var reduceRealisateur = function(directorId, titres) { ... var res = new Object(); ... res.director = directorId; ... res.films = titres; ... return res; ... }; movies>
Important - La fonction construit la valeur de résultat comme un objet res auquel on affecte deux propriétés: director et titres.
Pour lancer le traitement, il convient d'exécuter la commande suivante qui appelle la fonction mapReduce sur la collection movies :
movies>db.movies.mapReduce(mapRealisateur, reduceRealisateur, {out: {"inline": 1}} ) { "results" : [ { "_id" : "artist:1", "value" : "Marie Antoinette" }, { "_id" : "artist:10", "value" : "Volte/Face" }, { "_id" : "artist:101", "value" : { "director" : "artist:101", "films" : [ "Eyes Wide Shut", "Shining" ] } }, { "_id" : "artist:111", "value" : { "director" : "artist:111", "films" : [ "Jeanne d'Arc", "Le cinquième élément", "Léon", "Nikita", "Le grand bleu" ] } }, { "_id" : "artist:122", "value" : { "director" : "artist:122", "films" : [ "King of New York", "Bad Lieutenant" ] } }, { "_id" : "artist:13", "value" : "Sleepy Hollow" }, { "_id" : "artist:135", "value" : "The Matrix Revolutions" }, { "_id" : "artist:138", "value" : "De bruit et de fureur" }, { "_id" : "artist:142", "value" : "Usual suspects" }, { "_id" : "artist:168", "value" : "Une journée en enfer" }, { "_id" : "artist:17", "value" : { "director" : "artist:17", "films" : [ "American Beauty", "Skyfall" ] } }, ...
Important - Le premier paramètre est la fonction de map, le second la fonction de reduce, et le troisième indique la sortie, ici l’écran.
MapReduce peut prendre plusieurs options dont une s'avère particuluièrement utile, à savoir le résultat d’une requête :
movies>db.movies.mapReduce(mapRealisateur, reduceRealisateur, ... {out: {"inline": 1}, query: {"country": "USA"}} ) { "results" : [ { "_id" : "artist:1", "value" : "Marie Antoinette" }, { "_id" : "artist:10", "value" : "Volte/Face" }, { "_id" : "artist:101", "value" : "Eyes Wide Shut" }, { "_id" : "artist:122", "value" : { "director" : "artist:122", "films" : [ "King of New York", "Bad Lieutenant" ] } }, { "_id" : "artist:13", "value" : "Sleepy Hollow" }, { "_id" : "artist:135", "value" : "The Matrix Revolutions" }, { "_id" : "artist:142", "value" : "Usual suspects" }, { "_id" : "artist:168", "value" : "Une journée en enfer" }, { "_id" : "artist:17", "value" : { "director" : "artist:17", "films" : [ "American Beauty", "Skyfall" ] } },
Références
<html>
Copyright © 2004-2017 I2TCH LIMITED.<br><br>
</html>