2012-06-18 22 views
7

Używam java/morphia do czynienia z mongodb. Domyślny obiekt ObjectId nie jest zbyt wygodny w użyciu z warstwy Java. Chciałbym, aby był to typ String, zachowując proces generowania kluczy za pomocą ObjectId, na przykład _id = new ObjectId.toString().Czy mogę użyć String jako typu ID dla dokumentu mongodb?

Chcę wiedzieć, czy są jakieś efekty uboczne, które robią to w ten sposób? Na przykład czy wpłynie to na wydajność bazy danych lub spowoduje kluczowe konflikty w jakikolwiek sposób? Czy wpłynie to na zmienne środowisko ...

+0

Czy możesz wyjaśnić, dlaczego ObjectId jest niewygodny? Możesz łatwo odtworzyć jeden z ciągu takiego jak 'id = new ObjectId (str)' –

+0

String jest typem używanym w każdym programie Java, podczas gdy ObjectId nie jest. Nie chcę wprowadzać nowego typu do innych komponentów korzystających z mojej biblioteki. prawdopodobnie będzie to wymagać importu morfiny, mongodb i biblioteki bons, to jest jeszcze lepsze, jeśli ludzie używający mojej biblioteki są transparentni dla typów mongodb, w tym ObjectId –

+0

Hmm ... ale jeśli twoja biblioteka przechowuje dane w Mongo, to nie będzie mongo.jar i tak musi być w ścieżce klas? Ponadto istnieje napowietrzne tworzenie i usuwanie wielu ciągów Strings. –

Odpowiedz

18

Możesz użyć dowolnego rodzaju wartości dla pola _id (z wyjątkiem Tablic). Jeśli zdecydujesz się nie używać ObjectId, będziesz musiał w jakiś sposób zagwarantować wyjątkowość wartości (zrobi to ObjectId do napisu). Jeśli spróbujesz wstawić zduplikowany klucz, wystąpi błąd i będziesz musiał sobie z nim poradzić.

Nie jestem pewien, jaki efekt będzie miał na grupę z sharded, gdy spróbujesz wstawić dwa dokumenty z tym samym _id do różnych odłamków. Podejrzewam, że pozwoli ci to wstawić, ale to cię ugryzie. (Będę musiał to przetestować).

Powiedziawszy, nie powinieneś mieć problemów z _id = (new ObjectId).toString().

+0

To dobrze. dzięki! –

+0

Twoje drugie i trzecie zdanie są przeciwko sobie. Trzeci jest poprawny. Nie podejrzewaj w odpowiedziach. Również '_id's może przechowywać wartość typu' tablica'. – Dyin

+0

Jak dokładnie się ze sobą sprzeczają? –

4

Tak naprawdę zrobiłem to samo, ponieważ miałem problem z konwersją ObjectID na JSON.

Potem zrobił coś podobnego

@Id 
private String id; 
public String getId() { 
    return id(); 
} 
public void setId(String id) { 
    this.id = id; 
} 

i wszystko działało w porządku aż postanowiłem zaktualizować uprzednio włożonego dokumentu, gdy mam obiektu przez ID wysłał go na stronę za pośrednictwem JSON i otrzymać ten sam zaktualizowany obiekt również przez post JSON, a następnie użył funkcji zapisu z Datastore, zamiast aktualizować poprzednie dane, wstawił nowy dokument zamiast aktualizowania tego, który już był.

Nawet najgorszy nowy dokument miał ten sam identyfikator, co wcześniej wstawiony, coś, co uważałem za niemożliwe.

W każdym razie ustawiłem prywatny obiekt jako ObjectID i po prostu zostawiłem get jako łańcuch, a następnie zadziałało zgodnie z oczekiwaniami, nie będąc pewnym, czy pomaga to w twoim przypadku.

@Id 
private ObjectId id; 
public String getId() { 
    return id.toString(); 
} 
public void setId(String id) { 
    this.id = new ObjectId(id); 
} 
1

Tak, możesz użyć ciągu jako _id.

Polecam go tylko, jeśli masz jakąś wartość (w dokumencie), która oczywiście jest dobrym unikalnym kluczem. Użyłem tego projektu w jednej kolekcji, w której znajdował się ciąg znaków geo-tag, w postaci "xxxxyyyy"; to pole unikatowego dokumentu musiało znajdować się w dokumencie i Musiałem zbudować na nim indeks ... więc dlaczego nie użyć go jako klucza? (Pozwoliło to uniknąć jednej dodatkowej pary klucz-wartość, I uniknął drugiego indeksu w kolekcji, ponieważ MondoDB naturalnie buduje indeks na "_id". Biorąc pod uwagę rozmiar kolekcji, oba z nich przyczyniły się do poważnych oszczędności miejsca.)

Jednak z tonu pytania ("ObjectIDs nie są bardzo wygodne"), jeśli jedynym powodem, dla którego chcesz użyć ciągu znaków, nie chcesz mieć kłopotów z ustaleniem, jak starannie zarządzać ObjectIDami. Sugeruję, że warto poświęcić swój czas, aby się do nich zbliżyć. Jestem pewien, że nie stanowią one problemu ... kiedy odkryjesz swój problem z nimi.

W przeciwnym razie: jakie są opcje? Czy wymyślisz identyfikatory ciągów KAŻDYM CZASEM, w którym używasz MongoDB w przyszłości?

+1

Hej dziękuję za powrót do mojego pytania zadawanego prawie cztery lata temu. Wydaje mi się, że od tego czasu mam więcej zrozumienia na temat MongoDB. A teraz uważam przechowywanie ObjectId za ciąg znaków, to naprawdę zły pomysł, ponieważ ObjectId jest dosłownie trzema liczbami całkowitymi, natomiast reprezentacja String to 24 znaki, co nie jest wydajne zarówno pod względem czasu, jak i przestrzeni. –

1

Chciałbym dodać, że nie zawsze dobrze jest używać wygenerowanego automatycznie identyfikatora obiektu BSON jako unikalnego identyfikatora, jeśli zostanie on przekazany aplikacji: może on zostać zmanipulowany przez użytkownika. Identyfikatory obiektów wydają się generowane sekwencyjnie, więc jeśli nie uda się wprowadzić niezbędnych mechanizmów autoryzacji, złośliwy użytkownik może po prostu zwiększyć wartość, jaką ma, aby uzyskać dostęp do zasobów, do których nie powinien mieć dostępu.

Dlatego używanie identyfikatorów typu UUID zapewni warstwę bezpieczeństwa przez nieprzejrzystość. Oczywiście autoryzacja (czy ten użytkownik ma dostęp do żądanego zasobu) jest koniecznością, ale powinieneś być świadomy wspomnianej wyżej funkcji ObjectID.

Aby uzyskać najlepsze z obu światów, należy wygenerować UUID, który pasuje do długości ObjectID (12 lub 24 znaki) i użyć go do utworzenia własnego _id typu ObjectID.

+2

"jeśli nie wprowadzisz koniecznej autoryzacji" i tak jesteś skazany na niepowodzenie. Niejasność nie jest bezpieczeństwem. To tylko oszukiwanie siebie "jesteśmy bezpieczni". – Piohen

+0

@ Piohen, jak ludzie nie potrafią przeczytać drugiego akapitu, jest poza mną ... –