MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Holen Sie sich die zuletzt eingefügte Dokument-ID in MongoDB mit dem Java-Treiber

1. Übersicht

Manchmal benötigen wir die ID eines Dokuments, das wir gerade in eine MongoDB-Datenbank eingefügt haben. Wir möchten beispielsweise die ID als Antwort an einen Aufrufer zurücksenden oder das erstellte Objekt zum Debuggen protokollieren.

In diesem Tutorial sehen wir, wie IDs in MongoDB implementiert werden und wie die ID eines Dokuments, das wir gerade in eine Sammlung eingefügt haben, über ein Java-Programm abgerufen wird.

2. Was ist die ID eines MongoDB-Dokuments?

Wie in jedem Datenspeichersystem benötigt MongoDB eine eindeutige Kennung für jedes in einer Sammlung gespeicherte Dokument. Dieser Bezeichner entspricht dem Primärschlüssel in relationalen Datenbanken.

In MongoDB besteht diese ID aus 12 Bytes:

  • ein 4-Byte-Zeitstempelwert repräsentiert die Sekunden seit der Unix-Epoche
  • ein 5-Byte-Zufallswert, der einmal pro Prozess generiert wird. Dieser Zufallswert ist einzigartig für die Maschine und den Prozess.
  • ein 3-Byte-Inkrementierungszähler

Die ID wird in einem Feld namens _id gespeichert und wird vom Client generiert. Das bedeutet, dass die ID generiert werden muss, bevor das Dokument an die Datenbank gesendet wird. Auf der Clientseite können wir entweder eine vom Treiber generierte ID verwenden oder eine benutzerdefinierte ID generieren.

Wir können sehen, dass Dokumente, die von demselben Client in derselben Sekunde erstellt wurden, die ersten 9 Bytes gemeinsam haben. Daher beruht die Eindeutigkeit der ID in diesem Fall auf dem Zähler. Mit dem Zähler kann ein Kunde über 16 Millionen Dokumente in derselben Sekunde erstellen.

Obwohl es mit einem Zeitstempel beginnt, sollten wir darauf achten, dass der Bezeichner nicht als Sortierkriterium verwendet wird. Dies liegt daran, dass Dokumente, die in derselben Sekunde erstellt wurden, nicht garantiert nach dem Erstellungsdatum sortiert werden, da der Zähler nicht garantiert monoton ist. Außerdem können unterschiedliche Clients unterschiedliche Systemuhren haben.

Der Java-Treiber verwendet einen Zufallszahlengenerator für den Zähler, der nicht monoton ist. Aus diesem Grund sollten wir die vom Treiber generierte ID nicht zum Sortieren nach Erstellungsdatum verwenden.

3. Die ObjectId Klasse

Die eindeutige Kennung wird in einer ObjectId gespeichert Klasse, die praktische Methoden bereitstellt, um die in der ID gespeicherten Daten abzurufen, ohne sie manuell zu analysieren.

So erhalten wir beispielsweise das Erstellungsdatum der ID:

Date creationDate = objectId.getDate();

Ebenso können wir den Zeitstempel der ID in Sekunden abrufen:

int timestamp = objectId.getTimestamp();

Die ObjectId -Klasse stellt auch Methoden bereit, um den Zähler, die Maschinenkennung oder die Prozesskennung zu erhalten, aber sie sind alle veraltet.

4. Abrufen der ID

Das Wichtigste, woran Sie denken sollten, ist, dass der Client in MongoDB die eindeutige Kennung eines Dokuments generiert bevor es an den Cluster gesendet wird. Dies steht im Gegensatz zu Sequenzen in relationalen Datenbanken. Dies macht das Abrufen dieser ID ganz einfach.

4.1. Vom Fahrer generierte ID

Die standardmäßige und einfache Möglichkeit, die eindeutige ID eines Dokuments zu generieren ist, den Fahrer die Arbeit machen zu lassen. Wenn wir ein neues Dokument einfügen zu einer Sammlung , falls keine _id Feld existiert im Dokument , generiert der Treiber eine neue ObjectId bevor der Einfügungsbefehl an den Cluster gesendet wird.

Unser Code zum Einfügen eines neuen Dokuments in Ihre Sammlung kann so aussehen:

Document document = new Document();
document.put("name", "Shubham");
document.put("company", "Baeldung");
collection.insertOne(document);

Wir können sehen, dass wir nie angeben, wie die ID generiert werden muss.

Wenn die insertOne() -Methode zurückgibt, können wir die generierte ObjectId erhalten aus dem Dokument :

ObjectId objectId = document.getObjectId("_id");

Wir können auch die ObjectId abrufen wie ein Standardfeld des Dokuments und wandeln Sie es dann in ObjectId um :

ObjectId oId = (ObjectId) document.get("_id");

4.2. Benutzerdefinierte ID

Die andere Möglichkeit, die ID abzurufen, besteht darin, sie in unserem Code zu generieren und in das Dokument einzufügen wie jedes andere Feld. Wenn wir ein Dokument senden mit einer _id Feld an den Treiber, es wird kein neues generiert.

Wir benötigen dies möglicherweise in einigen Fällen, in denen wir die ID des Dokuments von MongoDB benötigen bevor Sie das Dokument einlegen in der Sammlung .

Wir können eine neue ObjectId generieren indem Sie eine neue Instanz der Klasse :

erstellen
ObjectId generatedId = new ObjectId();

Oder wir können auch das statische get() aufrufen Methode der ObjectId Klasse:

ObjectId generatedId = ObjectId.get();

Dann müssen wir nur noch unser Dokument erstellen und verwenden Sie die generierte ID. Dazu können wir es im Dokument bereitstellen Konstruktor:

Document document = new Document("_id", generatedId);

Alternativ können wir put() verwenden Methode:

document.put("_id", generatedId);

Bei der Verwendung einer nutzergenerierten ID müssen wir vorsichtig sein, wenn wir eine neue ObjectId generieren vor jedem Einfügen, da doppelte IDs verboten sind. Doppelte IDs führen zu einer MongoWriteException mit einer doppelten Schlüsselbotschaft.

Die ObjectId Die Klasse bietet mehrere andere Konstruktoren, mit denen wir einige Teile des Bezeichners festlegen können:

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)

Wir sollten jedoch sehr vorsichtig sein, wenn wir diese Konstruktoren verwenden, da die Eindeutigkeit der dem Treiber bereitgestellten ID vollständig von unserem Code abhängt. In diesen besonderen Fällen kann es zu Fehlern wegen doppelter Schlüssel kommen:

  • wenn wir dieselbe Kombination aus Datum (oder Zeitstempel) und Zähler mehrmals verwenden
  • Wenn wir denselben hexadezimalen String verwenden , Byte Array oder ByteBuffer mehrmals