Premiers pas avec MongoDB

MongoDB est une base de données orientée document. On y retrouve la possibilité de stocker des collections d’objets dans des tables sans avoir de schéma prédéterminé. Pour tous ceux qui ont de l’expérience avec les bases de données SQL, cette nouvelle approche peut être un peu déroutante au début. Je vais donc essayer de donner les premières pistes qui permettront à quiconque de débuter avec les bases de données NoSQL.

Installation de MongoDB

Avant toute chose, il faut installer le moteur de base en lui-même. Pour cela je propose une solution simple : Chocolatey. Lorsque Chocolatey est installé, on peut installer Mongo DB et MongoVue avec les commandes suivantes dans un command prompt :

cinst mongodb
cinst mongovue

Contexte et exemples

Afin d’illustrer cet article j’ai créé un projet dont seront tirés les exemples à suivre. Il s’agit de la gestion d’achat de livres par des clients d’une librairie. On retrouve donc une liste de clients, de livres et d’achat. Le code de cet exemple est disponible sur GitHub à l’adresse suivante : https://github.com/Cellenza/BLOG-MongoDb.

diagramme de classe

L’application qui découle de ce projet est relativement simple et se décompose en trois parties. La première sur la gauche comporte la liste des actions disponibles comme l’ajout de clients, des requêtes ou encore la suppression d’une collection. La seconde au milieu contient le log des opérations effectuées. Enfin la dernière sur la droite est la courbe qui donne la mesure du temps nécessaire pour insérer des données. Les insertions en masse sont effectuées par lots successifs et on peut ainsi observer les temps de réponse.

demo

Ajout de la référence NuGet et création de la connexion

Maintenant que la base de données est installée et prête à l’emploi, il faut pour l’utiliser ajouter dans le projet la référence NuGet au driver.

mongodb nuget

Ensuite il est possible de se connecter au serveur en utilisant le code ci-dessous. La variable « database » permet d’effectuer ensuite toutes les opérations sur la base. Il est important de noter que la base sera créée lors de la première utilisation. Il n’est donc pas nécessaire de la créer auparavant.

this.server = MongoServer.Create(
new MongoConnectionStringBuilder("Server=localhost:27017"));
this.database = this.server.GetDatabase("MyMongoDb");

Insertion de données

La première étape consiste généralement à vouloir insérer des données dans un table. C’est ici que survient le premier changement majeur par rapport à une base SQL. Comme il n’y a pas de schéma, il n’est pas nécessaire de créer la table dans laquelle on souhaite insérer les données. C’est lors du premier insert qu’elle sera créée. Coté code, il est possible d’insérer deux types de données, soit une classe soit un document Bson. Ces deux méthodes sont équivalentes sachant que dans le premier cas l’objet sera converti en document Bson. Voici donc un exemple d’insertion batch de plusieurs clients :

MongoCollection clients = this.database.GetCollection("Client");
clients.InsertBatch(this.generator.GetClientRandomn(number));
						
MongoCollection clients = this.database.GetCollection("Client");
clients.InsertBatch(this.generator.GetClientWithAgeRandomn(number));

Recherche

La recherche est relativement simple car, contrairement à une requête SQL, on ne peut la faire que sur une seule collection. Voici donc un exemple de requête qui va sélectionner les clients qui habitent un pays donné et ayant un âge supérieur a celui passé en paramètre :

List result = new List();

MongoCollection collection = this.database.GetCollection("Client");

QueryComplete query = Query.And(
Query.EQ("Country", country), Query.GTE("Age", new BsonInt32(age)));
foreach (Client client in collection.FindAs(query))
{
    result.Add(client.ToString());
}

Suppression

Voici ci-dessous un exemple de suppression qui va détruire l’ensemble de la collection :

this.database.DropCollection("Client");

Exécution d’une commande

Il est également possible d’exécuter un certain nombre de commande dont celle qui permet de connaitre le nombre de lignes d’une collection : « count ». Voici comment il est possible d’en obtenir le résultat :

CommandResult r = this.database.RunCommand(
new CommandDocument(new BsonElement("count", "Client")));
if (r.Ok)
{
    return r.Response.GetValue("n").AsDouble;
}
return 0;

Map/Reduce

Cette fonctionnalité qui n’a pas d’équivalent dans le monde du SQL est très intéressante car elle permet d’effectuer un traitement spécifique sur l’ensemble d’une table. Pour cela il faut définir deux fonctions :

  • La première appelée « map » doit, pour un document (ligne), définir une clé et une valeur. La clé permettra d’effectuer un regroupement sur les données.
  • La seconde appelée « reduce » effectuera un traitement précis pour chaque clé. En effet l’ensemble des documents qui ont la même clé seront passés en paramètre et il sera possible d’itérer dessus afin d’effectuer un traitement.

Dans notre cas on calcule le nombre de livres vendus. Illustrons tout cela avec un exemple :

string map = "function() {" +
             "  emit({id : this.BookId}, {qty : this.Quantity});" +
             "}";

string reduce = "function(key, emits) {" +
                "    var reduced = { id : key.id, qty : 0};" +
                "    emits.forEach(function(val) {" +
                "        reduced.qty += val.qty;" +
                "    });" +
                "    return reduced;" +
                "}";

MongoCollection collection = this.database.GetCollection("Purchase");
MapReduceResult mr = collection.MapReduce(map, reduce);

Conclusion

Le concept NoSQL est intéressant et cela pour plusieurs raisons. La première est l’absence de schéma qui permet d’avoir une grande flexibilité dans le stockage des données. Je pense que cette approche est relativement pragmatique car combien de fois j’ai pu voir des bases de données SQL sans aucune contrainte entre les tables et avec des colonnes contenant du xml pour permettre d’ajouter « plus facilement » une nouvelle colonne. Ensuite la facilité de mise en œuvre est vraiment appréciable, il n’y a pas d’installation complexe et on peut commencer un développement en quelques minutes. La montée en charge est un point fort de ce type de base notamment en utilisant le Sharding (répartition des données sur autant de serveur que nécessaire).

Malgré tous ces avantages, le NoSQL ne sera sans doute pas adapté à tous les besoins car le manque de jointure, de transaction, de mécanisme avancé de recovery par exemple pourront éliminer ce choix. Mais il est désormais nécessaire de se poser la question en fonction de son besoin pour le faire le bon choix du type de base de donnée que vous allez utiliser.

Pas de commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *