1. Présentation
Parfois, nous avons besoin de l'ID d'un document que nous venons d'insérer dans une base de données MongoDB. Par exemple, nous pouvons vouloir renvoyer l'ID en réponse à un appelant ou enregistrer l'objet créé pour le débogage.
Dans ce tutoriel, nous verrons comment les identifiants sont implémentés dans MongoDB et comment récupérer l'identifiant d'un document que nous venons d'insérer dans une collection via un programme Java.
2. Qu'est-ce que l'ID d'un document MongoDB ?
Comme dans tout système de stockage de données, MongoDB a besoin d'un identifiant unique pour chaque document stocké dans une collection. Cet identifiant est équivalent à la clé primaire dans les bases de données relationnelles.
Dans MongoDB, cet ID est composé de 12 octets :
- une valeur d'horodatage de 4 octets représente les secondes depuis l'époque Unix
- une valeur aléatoire de 5 octets générée une fois par processus. Cette valeur aléatoire est unique à la machine et au processus.
- un compteur incrémenté de 3 octets
L'ID est stocké dans un champ nommé _id et est généré par le client. Cela signifie que l'ID doit être généré avant d'envoyer le document à la base de données. Côté client, nous pouvons soit utiliser un ID généré par le conducteur, soit générer un ID personnalisé.
Nous pouvons voir que les documents créés par le même client dans la même seconde auront les 9 premiers octets en commun. Par conséquent, l'unicité de l'ID repose sur le compteur dans ce cas. Le compteur permet à un client de créer plus de 16 millions de documents dans la même seconde.
Bien qu'il commence par un horodatage, il faut faire attention à ce que l'identifiant ne soit pas utilisé comme critère de tri. En effet, il n'est pas garanti que les documents créés dans la même seconde soient triés par date de création, car le compteur n'est pas garanti d'être monotone. De plus, différents clients peuvent avoir des horloges système différentes.
Le pilote Java utilise un générateur de nombres aléatoires pour le compteur, qui n'est pas monotone. C'est pourquoi nous ne devons pas utiliser l'ID généré par le pilote pour trier par date de création.
3. L'ObjectId Classe
L'identifiant unique est stocké dans un ObjectId classe qui fournit des méthodes pratiques pour obtenir les données stockées dans l'ID sans les analyser manuellement.
Par exemple, voici comment obtenir la date de création de l'ID :
Date creationDate = objectId.getDate();
De même, on peut récupérer l'horodatage de l'ID en quelques secondes :
int timestamp = objectId.getTimestamp();
L'ObjectId fournit également des méthodes pour obtenir le compteur, l'identifiant de la machine ou l'identifiant du processus, mais elles sont toutes obsolètes.
4. Récupération de l'identifiant
La principale chose à retenir est que, dans MongoDB, le client génère l'identifiant unique d'un Document avant de l'envoyer au cluster. Cela contraste avec les séquences dans les bases de données relationnelles. Cela facilite la récupération de cet identifiant.
4.1. ID généré par le conducteur
Le moyen simple et standard de générer l'identifiant unique d'un document consiste à laisser le chauffeur faire le travail. Lorsque nous insérons un nouveau Document à une Collection , si aucun _id champ existe dans le Document , le pilote génère un nouvel ObjectId avant d'envoyer la commande d'insertion au cluster.
Notre code pour insérer un nouveau Document dans votre Collection peut ressembler à ceci :
Document document = new Document();
document.put("name", "Shubham");
document.put("company", "Baeldung");
collection.insertOne(document);
Nous pouvons voir que nous n'indiquons jamais comment l'ID doit être généré.
Lorsque le insertOne() renvoie la méthode, nous pouvons obtenir le ObjectId généré du Document :
ObjectId objectId = document.getObjectId("_id");
Nous pouvons également récupérer l'ObjectId comme un champ standard du Document puis castez-le en ObjectId :
ObjectId oId = (ObjectId) document.get("_id");
4.2. Identifiant personnalisé
L'autre façon de récupérer l'ID est de le générer dans notre code et de le mettre dans le Document comme n'importe quel autre domaine. Si nous envoyons un Document avec un _id champ au pilote, il n'en générera pas un nouveau.
Nous pourrions l'exiger dans certains cas où nous avons besoin de l'ID du document MongoDB avant d'insérer le Document dans la Collection .
Nous pouvons générer un nouvel ObjectId en créant une nouvelle instance de la classe :
ObjectId generatedId = new ObjectId();
Ou, nous pouvons également invoquer le get() statique méthode de l'ObjectId classe :
ObjectId generatedId = ObjectId.get();
Ensuite, nous n'avons plus qu'à créer notre Document et utiliser l'ID généré. Pour ce faire, nous pouvons le fournir dans le Document constructeur :
Document document = new Document("_id", generatedId);
Alternativement, nous pouvons utiliser le put() méthode :
document.put("_id", generatedId);
Lors de l'utilisation d'un ID généré par l'utilisateur, nous devons être prudents pour générer un nouvel ObjectId avant chaque insertion, car les identifiants en double sont interdits. Les ID en double entraîneront une MongoWriteException avec un message clé en double.
L'ObjectId La classe fournit plusieurs autres constructeurs qui nous permettent de définir certaines parties de l'identifiant :
public ObjectId(final Date date)
public ObjectId(final Date date, final int counter)
public ObjectId(final int timestamp, final int counter)
public ObjectId(final String hexString)
public ObjectId(final byte[] bytes)
public ObjectId(final ByteBuffer buffer)
Mais nous devons être très prudents lorsque nous utilisons ces constructeurs car l'unicité de l'ID fourni au pilote repose entièrement sur notre code. Nous pouvons obtenir une erreur de clés en double dans ces cas particuliers :
- si nous utilisons plusieurs fois la même combinaison date (ou horodatage) et compteur
- Si nous utilisons la même chaîne hexadécimale , octet tableau ou ByteBuffer plusieurs fois