Czy możliwe jest wygenerowanie tego samego dokładnego obiektu Mongo ObjectId dla dokumentu w dwóch różnych kolekcjach? Zdaję sobie sprawę, że jest to na pewno bardzo mało prawdopodobne, ale czy jest to możliwe?
Nie sprecyzowując, powód, dla którego pytam, jest taki, że dzięki aplikacji, nad którą pracuję, pokazujemy publiczne profile wybranych urzędników, którzy mamy nadzieję przekształcić się w pełnoprawnych użytkowników naszej witryny. Mamy osobne kolekcje dla użytkowników i wybranych urzędników, którzy obecnie nie są członkami naszej witryny. Istnieją różne inne dokumenty zawierające różne dane o wybranych urzędnikach, które wszystkie odwzorowują z powrotem na osobę używającą wybranego przez siebie oficjalnego obiektu ObjectId.
Po utworzeniu konta nadal podkreślamy dane powiązane z wybranym urzędnikiem, ale teraz są one również częścią kolekcji użytkowników z odpowiednim ObjectId użytkownika, aby odwzorować ich profil na interakcje z naszą aplikacją.
Kilka miesięcy temu zaczęliśmy konwertować naszą aplikację z MySql na Mongo i podczas gdy przechodzimy, przechowujemy starszy identyfikator MySql dla obu tych typów danych, a także zaczynamy teraz przechowywać wybranych oficjalnych obiektów Mongo ObjectId u użytkowników dokument odwzorowujący z powrotem na wybrane oficjalne dane.
Zastanawiałem się nad określeniem nowego obiektu ObjectId jako poprzednio wybranego oficjalnego obiektu ObjectId, aby uprościć sprawę, ale chciałem się upewnić, że kolizja z żadnym istniejącym użytkownikiem ObjectId nie będzie możliwa.
Dzięki za wgląd.
Edycja: Wkrótce po opublikowaniu tego pytania zdałem sobie sprawę, że moje zaproponowane rozwiązanie nie było zbyt dobrym pomysłem. Lepiej byłoby po prostu zachować obecny schemat, który mamy na miejscu, i po prostu link do wybranego oficjalnego „_id” w dokumencie użytkownika.
Odpowiedzi:
Krótka odpowiedź
Wystarczy dodać bezpośrednią odpowiedź na początkowe pytanie: TAK, jeśli używasz generowania identyfikatorów obiektów BSON, to w przypadku większości sterowników identyfikatory prawie na pewno będą unikalne we wszystkich kolekcjach. Zobacz poniżej, co oznacza „prawie na pewno”.
Długa odpowiedź
Identyfikatory obiektów BSON generowane przez sterowniki Mongo DB najprawdopodobniej będą unikalne we wszystkich kolekcjach. Wynika to głównie z ostatnich 3 bajtów identyfikatora, który dla większości sterowników jest generowany przez statyczny licznik przyrostowy. Ten licznik jest niezależny od kolekcji; jest globalny. Na przykład sterownik Java używa losowo inicjowanej, statycznej wartości AtomicInteger.
Dlaczego więc w dokumentach z Mongo mówią, że identyfikatory są „wysoce prawdopodobne”, że będą unikalne, zamiast wprost twierdzić, że BĘDĄ niepowtarzalne? Mogą wystąpić trzy możliwości, w których nie otrzymasz unikalnego identyfikatora (daj mi znać, jeśli jest więcej):
Przed tą dyskusją pamiętaj, że identyfikator obiektu BSON składa się z:
[4 bajty sekund od epoki, 3-bajtowy hasz maszynowy, 2-bajtowy identyfikator procesu, 3-bajtowy licznik]
Oto trzy możliwości, więc sam ocenisz, jak prawdopodobne jest uzyskanie duplikatu:
1) Przepełnienie licznika: w liczniku są 3 bajty. Jeśli zdarzy się, że wstawisz ponad 16 777 216 (2 ^ 24) dokumentów w ciągu jednej sekundy, na tej samej maszynie, w tym samym procesie, możesz przepełnić inkrementujące bajty licznika i otrzymać dwa identyfikatory obiektów, które współużytkują ten sam czas, maszyna , wartości procesowe i licznikowe.
2) Licznik nie inkrementujący: niektórzy kierowcy Mongo używają liczb losowych zamiast inkrementujących liczby dla bajtów liczących. W takich przypadkach istnieje szansa 1/16 777 216 wygenerowania nieunikalnego identyfikatora, ale tylko wtedy, gdy te dwa identyfikatory zostaną wygenerowane w tej samej sekundzie (tj. Przed aktualizacją sekcji czasu identyfikatora do następnej sekundy), w tym samym maszyna w tym samym procesie.
3) Skrót maszyny i procesu do tych samych wartości. Identyfikator maszyny i wartości identyfikatora procesu mogą, w bardzo mało prawdopodobnym scenariuszu, odwzorować na te same wartości dla dwóch różnych maszyn. Jeśli tak się stanie, a jednocześnie dwa liczniki na dwóch różnych komputerach, w tej samej sekundzie, wygenerują tę samą wartość, to otrzymasz duplikat ID.
Oto trzy scenariusze, na które należy uważać. Scenariusz 1 i 3 wydają się bardzo mało prawdopodobne, a scenariusza 2 można całkowicie uniknąć, jeśli używasz odpowiedniego sterownika. Będziesz musiał sprawdzić źródło sterownika, aby się upewnić.
źródło
ObjectId
, co wcześniej, o ile skrót maszyny, identyfikator procesu i licznik wszystko to samoObjectId są generowane po stronie klienta w sposób podobny do UUID, ale z pewnymi ładniejszymi właściwościami do przechowywania w bazie danych, takimi jak z grubsza zwiększanie kolejności i kodowanie czasu ich tworzenia za darmo. Kluczową sprawą w twoim przypadku użycia jest to, że zostały zaprojektowane w celu zagwarantowania wyjątkowości z dużym prawdopodobieństwem, nawet jeśli są generowane na różnych komputerach.
Teraz, jeśli ogólnie odwołujesz się do pola _id, nie wymagamy unikatowości między kolekcjami, więc można bezpiecznie użyć starego _id. Jako konkretny przykład, jeśli masz dwie kolekcje
colors
ifruits
obie mogą jednocześnie mieć taki obiekt{_id: 'orange'}
.Jeśli chcesz dowiedzieć się więcej o tworzeniu ObjectIds, oto specyfikacja: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-BSONObjectIDSpecification
źródło
Jeśli ktoś ma problemy ze zduplikowanymi identyfikatorami obiektów Mongo, powinieneś wiedzieć, że pomimo mało prawdopodobnego wystąpienia duplikatów w samym Mongo, możliwe jest wygenerowanie duplikatów _id w PHP w Mongo.
Przypadek użycia, w którym zdarzało mi się to regularnie, dotyczy mnie, gdy przeglądam zestaw danych i próbuję wstrzyknąć dane do kolekcji.
Tablica przechowująca dane wstrzyknięcia musi zostać wyraźnie zresetowana przy każdej iteracji - nawet jeśli nie określono wartości _id. Z jakiegoś powodu proces INSERT dodaje Mongo _id do tablicy tak, jakby była zmienną globalną (nawet jeśli tablica nie ma zasięgu globalnego). Może to wpłynąć na ciebie, nawet jeśli wywołujesz wstawienie w oddzielnym wywołaniu funkcji, w którym normalnie oczekiwałbyś, że wartości tablicy nie będą wracać do funkcji wywołującej.
Istnieją trzy rozwiązania tego:
unset()
z pola _id z tablicyarray()
każdym razem, gdy przeglądasz zestaw danychDomyślam się, że jest to błąd w interfejsie PHP i nie tyle problem z Mongo, ale jeśli napotkasz ten problem, po prostu usuń _id i powinieneś być w porządku.
źródło
Nie ma żadnej gwarancji unikalności ObjectId we wszystkich kolekcjach. Nawet jeśli jest to bardzo mało prawdopodobne, byłby to bardzo słaby projekt aplikacji, który polegałby na wyjątkowości _id we wszystkich kolekcjach.
Można to łatwo przetestować w skorupce mangowej:
Więc absolutnie nie polegaj na tym, że _id jest unikatowy w różnych kolekcjach, a ponieważ nie kontrolujesz funkcji generowania ObjectId, nie polegaj na niej.
Możliwe jest stworzenie czegoś, co bardziej przypomina UUID, a jeśli zrobisz to ręcznie, możesz mieć lepszą gwarancję wyjątkowości.
Pamiętaj, że możesz umieszczać obiekty różnych „typów” w tej samej kolekcji, więc dlaczego nie po prostu umieścić dwóch „tabel” w tej samej kolekcji. Będą dzielić tę samą przestrzeń id, a tym samym będą gwarantowane unikalne. Przejście z „potencjalnego” na „zarejestrowanego” byłoby prostym przerzuceniem pola ...
źródło