Możliwość generowania duplikatów Mongo ObjectId w dwóch różnych kolekcjach?

Czy możliwe jest wygenerowanie tego samego obiektu Mongo dla dokumentu w dwóch różnych zbiorach? Zdaję sobie sprawę, że to bardzo mało prawdopodobne, ale czy to możliwe?

Bez zbytniego sprecyzowania, pytam, ponieważ za pomocą aplikacji, nad którą pracuję, pokazujemy publiczne profile wybranych urzędników, których mamy nadzieję przekształcić w pełnoprawnych użytkowników naszej strony. Mamy osobne kolekcje dla użytkowników i wybranych urzędników, którzy nie są obecnie członkowie naszej strony. Istnieją różne inne dokumenty zawierające różne fragmenty danych o wybranych urzędnikach, które mapują z powrotem do osoby używającej wybranego oficjalnego celu.

Po utworzeniu konta nadal podświetlamy dane, które są powiązane z wybranym urzędnikiem, ale teraz są również częścią kolekcji użytkowników z odpowiednim użytkownikiem, aby zmapować swój profil do interakcji z naszą aplikacją.

Zaczęliśmy konwertować nasze aplikacja z MySql do Mongo kilka miesięcy temu i podczas gdy jesteśmy w przejściu przechowujemy starszą MySql id dla obu tych typów danych, a także zaczynamy teraz przechowywać wybrany oficjalny obiekt Mongo w dokumencie użytkowników, aby odwzorować z powrotem do wybranych oficjalnych danych.

Rozważałem tylko podanie nowego Użytkownika ObjectId jako poprzedniego wybranego oficjalnego ObjectId, aby uprościć sprawę, ale chciałem się upewnić, że nie można mieć kolizji z żadnym istniejącym użytkownikiem ObjectId.

Dzięki za wgląd.

Edit: krótko po opublikowaniu tego pytania, zdałem sobie sprawę, że moje proponowane 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żytkowników.

Author: Community, 2011-01-13

4 answers

Krótka Odpowiedź

Aby dodać bezpośrednią odpowiedź na Twoje początkowe pytanie: tak, jeśli używasz generowania BSON Object ID, to dla większości sterowników identyfikatory będą prawie na pewno unikalne we wszystkich kolekcjach. Zobacz poniżej, co oznacza "prawie na pewno".

Długa Odpowiedź

BSON Object ID generowane przez sterowniki Mongo DB są wysoce prawdopodobne, że będą unikalne we wszystkich kolekcjach. Wynika to głównie z ostatnich 3 bajtów ID, które dla większości sterowników jest generowany przez statyczny licznik inkrementacji. Licznik ten jest niezależny od kolekcji; jest globalny. Na przykład sterownik Java używa losowo zainicjowanego, statycznego Atomicintegera.

Więc dlaczego w Mongo docs mówią, że identyfikatory są" wysoce prawdopodobne", aby być unikalne, zamiast wprost mówić, że będą unikalne? Mogą wystąpić trzy możliwości, w których nie otrzymasz unikalnego identyfikatora (proszę dać mi znać, jeśli jest ich więcej):

Przed tą dyskusją, przypomnijmy, że ID obiektu BSON składa się z:

[4 bajty sekund od epoki, 3 bajty hash maszyny, 2 bajty ID procesu, 3 bajty licznik]

Oto trzy możliwości, więc sam oceń, jak prawdopodobne jest, aby dostać dupe:

1) przepełnienie licznika: w liczniku są 3 bajty. Jeśli zdarzy ci się wstawić 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ć zwiększające się bajty licznika i zakończyć z dwoma identyfikatorami obiektów, które mają te same wartości czasu, Maszyny, procesu i licznika.

2) Licznik nie inkrementujący: niektóre sterowniki Mongo używają losowych liczb zamiast inkrementujących liczb dla bajtów licznika. W takich przypadkach istnieje 1/16, 777,216 szansa na wygenerowanie niepowtarzalnego identyfikatora,ale tylko wtedy, gdy te dwa identyfikatory zostaną wygenerowane w tej samej sekundzie (tj. przed sekcją czasową ID aktualizuje się do następnej sekundy), na tej samej maszynie, w tym samym procesie.

3) maszyna i proces hash do tych samych wartości. ID Maszyny i ID procesu mogą, w bardzo mało prawdopodobnym scenariuszu, mapować 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 maszynach, podczas tej samej sekundy, wygenerują tę samą wartość, wtedy otrzymasz duplikat ID.

Oto trzy scenariusze, na które należy uważać. Scenariusz 1 i 3 wydaje się mało prawdopodobny, a scenariusz 2 można całkowicie uniknąć, jeśli używasz odpowiedniego sterownika. Będziesz musiał sprawdzić źródło kierowcy, aby wiedzieć na pewno.

 331
Author: Raj Advani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-06 21:41:06

Obiekty 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ększenie kolejności i kodowanie czasu ich tworzenia za darmo. Kluczowe dla Twojego przypadku użycia jest to, że są one zaprojektowane tak, aby zagwarantować wyjątkowość z dużym prawdopodobieństwem, nawet jeśli są generowane na różnych maszynach.

Teraz, jeśli odnosisz się do pola _id w ogóle, nie wymagamy wyjątkowości między kolekcjami, więc można bezpiecznie ponownie użyć Stary _id. Jako konkretny przykład, jeśli masz dwie kolekcje, colors i fruits, obie mogą mieć jednocześnie obiekt taki jak {_id: 'orange'}.

Jeśli chcesz dowiedzieć się więcej o tym, jak tworzone są obiekty, oto Specyfikacja: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-BSONObjectIDSpecification

 15
Author: mstearn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-13 06:15:57

W przypadku, gdy ktoś ma problemy z duplikatami obiektów Mongo, powinieneś wiedzieć, że pomimo nieprawdopodobnej liczby dupków występujących w samym Mongo, możliwe jest wygenerowanie duplikatów _id za pomocą PHP w Mongo.

Przypadek użycia, w którym stało się to z regularnością dla mnie jest, gdy jestem zapętlenie przez zbiór danych i próbuje wprowadzić dane do kolekcji.

Tablica, która przechowuje dane iniekcji, musi być jawnie resetowana przy każdej iteracji-nawet jeśli nie podaje wartości _id. Z jakiegoś powodu proces wstawiania dodaje Mongo _id do tablicy tak, jakby była zmienną globalną (nawet jeśli tablica nie ma globalnego zakresu). Może to mieć wpływ nawet wtedy, gdy wywołujesz wstawianie w osobnym wywołaniu funkcji, w którym normalnie spodziewasz się, że wartości tablicy nie będą się utrzymywać z powrotem do funkcji wywołującej.

Istnieją trzy rozwiązania tego problemu:

  1. Możesz unset() pole _id z tablicy
  2. Możesz ponownie inicjalizuj całą tablicę za pomocą array() za każdym razem, gdy zapętlisz swój zbiór danych
  3. możesz jawnie zdefiniować wartość _id samodzielnie (dbając o to, aby zdefiniować ją w taki sposób, aby nie generować dups samodzielnie).

Domyślam się, że jest to błąd w interfejsie PHP, i nie tyle problem z Mongo, ale jeśli napotkasz ten problem, po prostu Odłącz _id i powinno być dobrze.

 12
Author: DenverMatt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-16 23:53:34

Nie ma żadnej gwarancji co do wyjątkowości obiektywizmu we wszystkich kolekcjach. Nawet jeśli jest to prawdopodobnie bardzo mało prawdopodobne, byłaby to bardzo słaba konstrukcja aplikacji, która opierała się na unikalności _id w różnych kolekcjach.

Można to łatwo przetestować w skorupie mongo:

MongoDB shell version: 1.6.5
connecting to: test
> db.foo.insert({_id: 'abc'})
> db.bar.insert({_id: 'abc'})
> db.foo.find({_id: 'abc'})
{ "_id" : "abc" }
> db.bar.find({_id: 'abc'})
{ "_id" : "abc" }
> db.foo.insert({_id: 'abc', data:'xyz'})
E11000 duplicate key error index: test.foo.$_id_  dup key: { : "abc" }

Więc absolutnie nie polegaj na tym, że _id jest unikalny w różnych kolekcjach, a ponieważ nie kontrolujesz funkcji generowania ObjectId, nie polegaj na niej.

Można stworzyć coś to bardziej jak uuid, a jeśli zrobisz to ręcznie, możesz mieć lepszą gwarancję wyjątkowości.

Pamiętaj, że możesz umieścić obiekty różnych" typów "w tej samej kolekcji, więc dlaczego nie umieścić dwóch" tabel " w tej samej kolekcji. Dzieliłyby One tę samą przestrzeń _id, a tym samym byłyby gwarantowane jako unikalne. Przejście z "perspektywicznego" na "zarejestrowanego"byłoby prostym przerzucaniem pola...

 -8
Author: slacy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-13 07:01:50