1. Przegląd
Czasami potrzebujemy identyfikatora dokumentu, który właśnie wstawiliśmy do bazy danych MongoDB. Na przykład możemy chcieć odesłać identyfikator jako odpowiedź do wywołującego lub zarejestrować utworzony obiekt w celu debugowania.
W tym samouczku zobaczymy, jak identyfikatory są implementowane w MongoDB i jak pobrać identyfikator dokumentu, który właśnie wstawiliśmy do kolekcji za pomocą programu Java.
2. Jaki jest identyfikator dokumentu MongoDB?
Jak w każdym systemie przechowywania danych, MongoDB potrzebuje unikalnego identyfikatora dla każdego dokumentu przechowywanego w kolekcji. Ten identyfikator jest odpowiednikiem klucza podstawowego w relacyjnych bazach danych.
W MongoDB ten identyfikator składa się z 12 bajtów:
- 4-bajtowa wartość znacznika czasu reprezentuje sekundy od epoki Uniksa
- 5-bajtowa losowa wartość generowana raz na proces. Ta losowa wartość jest unikalna dla maszyny i procesu.
- licznik przyrostowy o 3 bajty
Identyfikator jest przechowywany w polu o nazwie _id i jest generowany przez klienta. Oznacza to, że identyfikator musi zostać wygenerowany przed wysłaniem dokumentu do bazy danych. Po stronie klienta możemy użyć identyfikatora generowanego przez sterownik lub wygenerować identyfikator niestandardowy.
Widzimy, że dokumenty utworzone przez tego samego klienta w tej samej sekundzie będą miały wspólne pierwsze 9 bajtów. Dlatego unikalność identyfikatora zależy w tym przypadku od licznika. Licznik pozwala klientowi stworzyć ponad 16 milionów dokumentów w tej samej sekundzie.
Chociaż zaczyna się od znacznika czasu, powinniśmy uważać, aby identyfikator nie był używany jako kryterium sortowania. Dzieje się tak, ponieważ dokumenty utworzone w tej samej sekundzie nie mają gwarancji, że zostaną posortowane według daty utworzenia, ponieważ licznik nie ma gwarancji, że będzie monotoniczny. Ponadto różni klienci mogą mieć różne zegary systemowe.
Sterownik Java używa generatora liczb losowych dla licznika, który nie jest monotoniczny. Dlatego nie powinniśmy używać identyfikatora generowanego przez kierowcę do sortowania według daty utworzenia.
3. Id obiektu Klasa
Unikalny identyfikator jest przechowywany w ObjectId klasa, która zapewnia wygodne metody uzyskiwania danych przechowywanych w ID bez ich ręcznego parsowania.
Na przykład, oto jak możemy uzyskać datę utworzenia identyfikatora:
Date creationDate = objectId.getDate();
Podobnie możemy pobrać znacznik czasu identyfikatora w kilka sekund :
int timestamp = objectId.getTimestamp();
Id obiektu klasa dostarcza również metody do uzyskania licznika, identyfikatora komputera lub identyfikatora procesu, ale wszystkie są przestarzałe.
4. Pobieranie identyfikatora
Najważniejszą rzeczą do zapamiętania jest to, że w MongoDB klient generuje unikalny identyfikator Dokumentu przed wysłaniem go do klastra. Jest to w przeciwieństwie do sekwencji w relacyjnych bazach danych. To sprawia, że odzyskanie tego identyfikatora jest dość łatwe.
4.1. Identyfikator generowany przez kierowcę
Standardowy i łatwy sposób generowania unikalnego identyfikatora Dokumentu polega na umożliwieniu kierowcy wykonania pracy. Kiedy wstawiamy nowy dokument do kolekcji , jeśli nie _id pole istnieje w Dokumencie , sterownik generuje nowy ObjectId przed wysłaniem polecenia insert do klastra.
Nasz kod do wstawienia nowego Dokumentu do Twojej kolekcji może wyglądać tak:
Document document = new Document();
document.put("name", "Shubham");
document.put("company", "Baeldung");
collection.insertOne(document);
Widzimy, że nigdy nie wskazujemy, jak należy wygenerować identyfikator.
Kiedy insertOne() metoda zwraca, możemy uzyskać wygenerowany ObjectId z Dokumentu :
ObjectId objectId = document.getObjectId("_id");
Możemy również pobrać ObjectId jak standardowe pole Dokumentu a następnie prześlij go na ObjectId :
ObjectId oId = (ObjectId) document.get("_id");
4.2. Identyfikator niestandardowy
Innym sposobem na odzyskanie identyfikatora jest wygenerowanie go w naszym kodzie i umieszczenie w Dokumencie jak każda inna dziedzina. Jeśli wyślemy dokument z _id do sterownika, nie wygeneruje nowego.
Możemy tego wymagać w niektórych przypadkach, gdy potrzebujemy identyfikatora Dokumentu MongoDB przed wstawieniem Dokumentu w Kolekcji .
Możemy wygenerować nowy ObjectId tworząc nową instancję klasy :
ObjectId generatedId = new ObjectId();
Lub możemy również wywołać statyczne get() metoda ObjectId klasa:
ObjectId generatedId = ObjectId.get();
Następnie musimy tylko utworzyć nasz Dokument i użyj wygenerowanego identyfikatora. W tym celu możemy podać go w Dokumencie konstruktor:
Document document = new Document("_id", generatedId);
Alternatywnie możemy użyć put() metoda:
document.put("_id", generatedId);
Korzystając z identyfikatora generowanego przez użytkownika, musimy być ostrożni, aby wygenerować nowy ObjectId przed każdym wstawieniem, ponieważ zduplikowane identyfikatory są zabronione. Zduplikowane identyfikatory spowodują MongoWriteException ze zduplikowaną wiadomością klucza.
Id obiektu class udostępnia kilka innych konstruktorów, które pozwalają nam ustawić niektóre części identyfikatora:
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)
Ale powinniśmy być bardzo ostrożni, gdy używamy tych konstruktorów, ponieważ unikalność identyfikatora dostarczonego do sterownika zależy wyłącznie od naszego kodu. W tych szczególnych przypadkach możemy otrzymać błąd zduplikowanych kluczy:
- jeśli użyjemy tej samej kombinacji daty (lub znacznika czasu) i licznika kilka razy
- Jeśli użyjemy tego samego szesnastkowego ciągu , bajt tablica lub ByteBuffer kilka razy