MongoDB tout en douceur : deuxième partie

Dans ce deuxième article, on va aborder comment modifier ou supprimer des données ainsi que la gestion d’indexes.

Modification des données

La mise à jour des données se fait à l’aide de la commande « update » qui possède plusieurs paramètres.

Le premier paramètre est une requête qui permet de savoir quel(s) document(s) doivent être mis à jour. Sa syntaxe est exactement la même que pour la commande find. Passer un document vide revient à spécifier que tous les documents de la collection sont visés par la mise à jour.

Le second paramètre permet de spécifier les mises à jour a effectuer sur les documents ciblés. Il s’agit là encore d’un document au format JSON. Et son utilisation est à manier avec précautions. En effet, si on fait ce genre d’appel :

 db.personne.update({prenom : « Xavier »}, {age : 35})

le document répondant au critère sera entièrement remplacé par un nouveau document qui ne contiendra plus qu’un seul nouvel attribut, l’âge.

Il s’agit d’un vestige des premières moutures de la base, quand elle était considérée comme un conteneur d’objets et manipulée via des langages comme Javascript ou Python. Si on manipule la base avec ces langages (ou d’autres), on charge un objet complet, on le modifie puis on le met à jour dans la base. C’est pour cela que cette manière de faire existe encore dans les versions récentes de MongoDB.

Pour faire une mise à jour partielle d’un document, il faut utiliser le mot clé « $set ».

db.personne.update({prenom : « Xavier »}, {$set : {age : 35}})

Cette commande va mettre à jour le document répondant au critère passé en paramètre. Si l’attribut sur lequel porte la mise à jour existe, il est mis à jour. Dans le cas contraire, il est créé.

Il faut noter que si plusieurs documents répondent aux critères du query, seul le premier de ceux qui sont renvoyés est mis à jour. Pour mettre à jour tous les documents renvoyés par le query, il faut ajouter l’option « multi » à la commande d’update.

db.personne.update({prenom : « Xavier »}, {$set : {age : 35}}, {multi : 1})

Avec ce paramètre supplémentaire, tous les documents comportant un attribut prenom égal à Xavier seront mis à jour.

$set n’est pas le seul mot clé disponible pour mettre à jour des documents.

Les autres mots-clés sont :

$inc

$rename

$unset

$setOnInsert

$inc permet d’incrémenter le champ sélectionné du montant choisi.

Exemple :

db.personne.update({prenom : « Xavier »}, {$inc : {age : 2}})

Si le champ age existe, sa valeur est incrémentée de 2, sinon, il est créé avec la valeur 2. Si le champ ne contient pas de valeur numérique, une erreur est levée.

$rename permet de renommer un champ.

Exemple :

db.personne.update({prenom : « Xavier »}, {$rename : {age : « nombreAnnees »}})

Si le champ n’existe pas, les documents visés ne sont pas modifiés.

$unset permet de supprimer un champ présent dans un document.

Exemple :

db.personne.update({prenom : « Xavier »}, {$unset : {nombreAnnees : 1}})

Parmi les options de la méthode update, on peut également trouver le upsert. Si la valeur de ce paramètre vaut 1 ou true et qu’aucun document ne correspond à la partie critères de la commande de mise à jour, un nouveau document est créé avec les attributs de la partie critère et en appliquant les modifications spécifiée dans la partie « mise à jour ».

Etant donné qu’un document peut contenir des sous-documents, il est également possible de mettre à jour un champ d’un sous-document en utilisant l’opérateur « . ».

Par exemple, prenons le document suivant :

 

{« nom » : « Goscinny »,
« prenom » : « René »,
« adresse » : {« rue » : « Boulevard Astérix »,
« codePostal » : « 69001 »,
« ville » : « Lyon »}
}

Pour mettre à jour le code postal, il suffit d’un :

db.personne.update({« nom » : »Goscinny »}, {$set:{« adresse.codePostal » : »69002″}})

Suppression de documents

La suppression d’un ou plusieurs documents se fait via la commande « remove » à laquelle on passe en paramètre le query permettant d’identifier les documents visés.

 db.personne.remove({« prenom » : »Xavier »})

Si la commande est utilisée sans paramètres, la totalité des documents de la collection sont supprimés mais la collection existe toujours.

Pour supprimer une collection, il faut employer la commande « drop ».

db.personne.drop()

Gestion des indexes

Comme dans une base de donnée traditionnelle, il est possible de créer des indexes afin d’accélérer certaines recherches.

Les indexes sont portés par les collections. Ils peuvent concerner un champ ou plusieurs.

Comme dans tout système de base de données, si la création d’un index permet d’accélérer les recherches (parfois de manière impressionnante), cet index a aussi un impact, négatif celui-là, sur les actions de création et de modification de données.

A la création d’une collection, un index par défaut est créé qui va utiliser le _id de chaque document. Il s’agit là d’un index avec une contrainte d’unicité.

Une commande permet de savoir quels sont les indexes déclarés pour une collection donnée :

db.personne.getIndexes()

La liste de tous les indexes d’une base se fait avec la commande :

db.system.indexes.find()

La création d’un index se fait avec la commande « ensureIndex » :

db.personne.ensureIndex({« nom » : 1})

Si la valeur après le nom du champ à indexer vaut 1, l’index classera les documents sur une valeur croissante de ce champ. S’il vaut -1, les documents seront classés sur une valeur décroissante.

Si par la suite, on lance la requête suivante:

db.personne.find({« nom » : « Goscinny »}).explain()

Le résultat obtenu nous montre bien que l’index nouvellement créé a été utilisé :

{
« cursor » : « BtreeCursor nom_1 »,
« isMultiKey » : false,
« n » : 1,
« nscannedObjects » : 1,
« nscanned » : 1,
« nscannedObjectsAllPlans » : 1,
« nscannedAllPlans » : 1,
« scanAndOrder » : false,
« indexOnly » : false,
« nYields » : 0,
« nChunkSkips » : 0,
« millis » : 0,
« indexBounds » : {
« nom » : [
[
« Goscinny »,
« Goscinny »
]
]
},
« server » : « Benjamin-PC:27017 »
}

Un index peut également porter sur plusieurs champs :

db.personne.ensureIndex({« nom » : 1, « prenom » : -1})

Par défaut, un index est nommé en fonction des champs utilisés et de l’ordre de tri.

Par exemple, le dernier index créé a été nommé « nom_1_prenom_-1 ».

La méthode ensureIndex peut accepter un deuxième document en paramètre pour spécifier certaines options. Parmi ces options, il y a « name » qui permet de choisir comment nommer son index. La liste de toutes ces options est disponible dans la documentation officielle visible à l’adresse :

http://docs.mongodb.org/manual/reference/method/db.collection.ensureIndex/

Pour supprimer un index, il y a la solution de la suppression individuelle :

db.personne.dropIndex(« nom_de_l_index »)

Il y a aussi la possibilité de supprimer tous les indexes d’une collection :

db.personne.dropIndexes()

Il faut noter que cette dernière méthode ne supprime pas l’index unique basé sur l’id.

A propos Benjamin

Développeur Java, évangéliste du logiciel libre auprès de mes proches, j'essaie de concilier tout ça avec la curiosité qui m'a toujours fait avancer.
Ce contenu a été publié dans Développement, MongoDB. Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire

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

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.