NoSQL et MongoDB

MongoDB est une base de données NoSQL populaire orienté-document utilisant le langage JSON (BSON si compressé).

Voici un court tutoriel sur cette outil. Pour expérimenter, nous utiliserons une console texte de MongoDB (similaire à SQLPlus). Vous devez d’abord installer MongoDB sur votre système d’exploitation. Par la suite, vous avez le choix. Vous pouvez utiliser une base de donnée MongoDB local sur votre poste ou une base de données dans un nuage sur le site https://mongolab.com Sur ce site, vous vous créez un compte et vous créez ensuite une base de données « SandBox » (ce qui veut dire « test »). Dans votre console, vous allez vous connecter à votre base de données à distance par une commande similaire à la suivante:

mongo ds1234567.mongolab.com:61747/monMongoDB -u  utilisateur -p motdepasse

L’exemple utilisé pour ce tutoriel est celui du « cas projet ».

Créer une base de données

MongoDB est un système de gestion de base de données NoSQL de type document. Les documents sont regroupés sous forme de collections qui sont regroupées dans des bases de données. Nous allons créer une base de données appelée db et une collection projet0 qui contiendra les données de la base de données du projet 0 que vous connaissez. Voir les documents sur LEA.

Pour vérifier la présence des bases de données, on peut taper (mais il faut avoir les droits):

show dbs

Pour choisir une base de données (et la créer), on tape:

use db;

Pour savoir quelle base de données nous utilisons, on tape: db;

Créer et insérer dans une collection

Les données dans une base de données MongoDB sont regroupés par collection. Pour consulter les collections déjà présentes, on peut taper:

show collections;

Nous allons utiliser une première collection appelé projet0. Pour la créer, nous allons insérer un premier document. Par exemple, on affecte 1 « objet » Javascript à 1 variable appelée employe1.

employe1 = { nom : "Gagnon",
prenom : "Michel" };

On insère ces objets dans la collection comme suit:

db.projet0.insert( employe1 )

On peut constater le contenu de notre collection en exécutant:

projet0.find()

En exécutant, vous constaterez que des clés artificielles uniques ont été ajoutées accessibles par l’objet « _id » qui sont des objets spéciaux de MongoDB. On peut générer ces clés uniques par la fonction ObjectId().

Suivant les explications sur le site d’aide de MongoDB à propos de la création, voici comment créer un premier enregistrement de type employé et le lier à un premier département créé appelé Recherche & développement.

Mais avant cela, nous devrions détruire le document créé précédemment à partir de la variable employe1 puisqu’il est incomplet Pour ce faire, nous exécutons:

db.projet0.remove({ nom : "Gagnon",
prenom : "Michel" }, 1)

Pour en savoir plus sur la suppression de documents, consultez la page suivante.

Voici maintenant comment insérer un premier département et un premier employé pour ce département. id_departement = “RD”;

departement1 = {
_id: id_departement_RD,
nom_departement : id_departement_RD,
nom_complet: "Recherche et développement",
telephone: "418-567-8901"};

db.projet0.insert(departement1);

Pour créer notre employé pour ce département, on écrit par exemple:

db.projet0.insert(
{
no_employe: 1,
nas: "123456789",
nom: "Gagnon",
prenom: "Michel",
sexe: "M",
date_naissance: new Date('Jun 07, 1954'),
date_embauche: new Date('Jun 07, 1999'),
fonction: "programmeur",
salaire: 50000,
id_departement: id_departement_RD
}
)

Remarquez que les objets date sont créés à l’aide d’une fonction Date.

Pour en savoir plus sur la création et la mise à jour dans MongoDB, consultez la page suivante. Séquences

Il est possible de créer des séquences en créant d’abord un document de départ. Voici un exemple pour une séquence pour un numéro d’employé:

db.compteurs.insert(
{
_id: "employe_id",
seq: 0
}
)

Par la suite, on définit une fonction générale de type « Nextval » comme suit:

function getNextSequence(name) {
var ret = db.compteurs.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);

return ret.seq;
}

On peut alors utiliser cette fonction comme séquence comme suit:

db.projet0.insert(
{
no_employe: getNextSequence("employe_id"),
nas: "123456789",
nom: "Gagnon",
prenom: "Michel",
sexe: "M",
date_naissance: new Date('Jun 07, 1954'),
date_embauche: new Date('Jun 07, 1999'),
fonction: "programmeur",
salaire: 50000,
id_departement: id_departement_RD
}
)

Pour en savoir plus sur les séquences, voir ici.

Exercice 1

Servez-vous du fichier SQL du projet 0 (fourni sur LEA) pour créer le même ensemble de données sous MongoDB. Créez-vous un fichier contenant l’ensemble des définitions JSON de création des données. Utilisez la fonction copier/coller de votre fichier vers un interpréteur MongoDB. Vous pouvez mettre l’ensemble des données dans la collection projet0 ou bien vous pouvez créer plusieurs collections (une pour chaque table SQL). Chercher des documents Pour la suite de ce texte, nous supposons que vous avez créer l’ensemble des données du projet 0. Pour obtenir la liste des documents installés, vous tapez:

db.projet0.find();

Pour obtenir un document en particulier, on peut écrire:

db.projet0.find({ nom: "Gagnon"});

Pour filtrer, on peut utiliser des opérateurs (plus grand):

db.projet0.find({ salaire: {'$gt': 40000});

Compter et grouper des résultats Il est possible de compter le nombre de documents dans une collection comme par exemple:

db.projet0.count();

On peut « grouper » et obtenir les valeurs distinctes dans une collection. Par exemple, on tape la commande suivante:

db.projet0.distinct("prenom");

On obtient la liste des prénoms sans répétition. De façon plus complexe, il est possible de grouper des résultats de façon équivalente à un GROUP BY. Par exemple, pour compter le nombre d’employés par profession (attribut « fonction »), on écrit ceci:

db.projet0.group(
{
key: {'fonction': true},
initial: {total: 0},
reduce: function(doc, prev) { prev.total += 1}
});

Le document passé en paramètre à la fonction group contient 3 sous-documents. Il y a le nom de l’attribut de regroupement (paramètre du GROUP BY). Il y a le nom de la variable de décompte (total). Le 3ième paramètre est une fonction Javascript qui prend en paramètre le document « employe » et le document du décompte (contenant l’attribut « total »). On peut modifier le regroupement pour calculer le total du salaire par profession comme suit: db.projet0.group( { key: {‘fonction’: true}, initial: {salaire_total: 0}, reduce: function(doc, prev) { prev.salaire_total += doc.salaire } });

Exercice 2

Trouvez le moyen d’obtenir le nombre d’employés par nom de département.

Pour en savoir plus les techniques de regroupement dans MongoDB, lire le texte disponible ici.

Introduction au Map/reduce

La technique de programme map/reduce a été développé par Google. Elle est souvent utilisé dans le monde NoSQL. L’idée est simple. La fonction « map » est appliquée sur chaque document. Et la fonction « reduce » rassemble les résultats de façon successible jusqu’au résultat total. Dans le cas du projet 0, imaginons que nous voudrions obtenir le nombre de documents pour chaque projet (voir le modèle MRD). Pour ce faire, nous avons besoin d’une fonction qui appliqué à chaque document. Cette fonction s’appelle un « map ».

var map = function() {
emit(this.nom_client, {documents: 1});
};

On doit aussi définir la fonction reduce qui récoltera les résultats

var reduce = function(key, values) {
var somme = 0;
values.forEach(function(doc) {
somme += 1;
});

return {documents: somme};
};

On démarre le calcul comme suit:

var op = db.projet0.mapReduce(map, reduce, {out: "m_resultats"});

Pour obtenir le résultat, on doit lister les résultats comme suit:

db[op.result].find();

Exercice 3

Appliquez la technique map/reduce pour calculer le nombre de projets par client.