2012-10-18 12 views
7

Chcę uzyskać klucz encji znający identyfikator jednostki i przodka. ID jest unikalne w obrębie grupy encji zdefiniowanej przez przodka. Wydaje mi się, że nie jest to możliwe przy użyciu interfejsu ndb. Rozumiem, że datastore może być spowodowane faktem, że ta operacja wymaga wykonania pełnego skanowania indeksu. Obejście, którego użyłem, polega na utworzeniu obliczonej właściwości w modelu, która będzie zawierała część identyfikatora klucza. Jestem w stanie teraz zrobić kwerendę przodka i uzyskać kluczKlucz podmiotu pobierającego ndb o identyfikatorze bez rodzica

class SomeModel(ndb.Model): 
    ID = ndb.ComputedProperty(lambda self: self.key.id()) 

    @classmethod 
    def id_to_key(cls, identifier, ancestor): 
     return cls.query(cls.ID == identifier, 
         ancestor = ancestor.key).get(keys_only = True) 

wydaje się działać, ale czy są jakieś lepsze rozwiązania tego problemu?

Aktualizacja Wydaje się, że dla magazynu danych naturalnym rozwiązaniem jest użycie pełnych ścieżek zamiast identyfikatorów. Początkowo myślałem, że będzie to zbyt uciążliwe. Po przeczytaniu odpowiedzi Dragonx przeprojektowałem moją aplikację. Ku mojemu zdziwieniu wszystko wygląda teraz znacznie prościej. Dodatkowymi korzyściami są to, że moje podmioty wykorzystają mniej miejsca i nie będę potrzebować dodatkowych indeksów.

+0

Brzmi jak masz właściwą odpowiedź! –

+0

ID to _nie_ gwarantowane unikalne w ramach grupy encji - tylko dla danej jednostki nadrzędnej. –

Odpowiedz

8

Wpadłem też na ten problem. Myślę, że masz rozwiązanie.

Lepszym rozwiązaniem byłoby zaprzestanie używania identyfikatorów do odwoływania się do encji i przechowywanie rzeczywistego klucza lub pełnej ścieżki.

Wewnętrznie używam kluczy zamiast identyfikatorów.

W moim interfejsie API odpoczynku użyłem http://url/kind/id (gdzie id wyglądał jak "123") w celu pobrania obiektu. Zmodyfikowałem to, aby podać pełną ścieżkę przodka do obiektu: http://url/kind/ancestor-ancestor-id (789-456-123), następnie przeanalizowałem ten ciąg, wygenerowałem klucz, a następnie otrzymałem klucz.

+0

Masz rację. Wszystko jest łatwiejsze dzięki pełnej ścieżce przodka. Wydaje się, że jest to właściwy sposób robienia takich rzeczy w magazynie danych. Dzięki –

+0

Nie zapomnij, że w magazynie danych istnieje "klucz", którego można użyć do przechowywania rzeczywistych kluczy (KeyProperty). –

+0

W notatce bocznej Java ma [te metody] (https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/KeyFactory#keyToString%28com.google.appengine .api.datastore.Key% 29) do serializacji i deserializacji kluczy – aimless

3

Skoro masz pełną informację o swoim przodku i znasz swój identyfikator, można bezpośrednio utworzyć klucz i uzyskać podmiot, w następujący sposób:

my_key = ndb.Key(Ancestor, ancestor.key.id(), SomeModel, id) 
entity = my_key.get() 

W ten sposób można uniknąć dokonywania kwerendy, która kosztuje więcej niż Operacja zarówno pod względem pieniądza, jak i szybkości.

Mam nadzieję, że to pomoże.

+1

To dobre rozwiązanie, jeśli przodek jest także rodzicem, ale nie jest to mój przypadek. –

+0

Ponieważ użyłeś terminu "przodek", myślałem, że masz na myśli, że był rodzicem. Jeśli tak nie jest, to twoje podejście jest prawidłowe. –

1

Chcę zrobić mały dodatek do odpowiedzi dargonx.

W mojej aplikacji na front-end używam reprezentację ciąg klawiszy:

str(instance.key()) 

Kiedy trzeba dokonać pewnych zmian z instence nawet jeśli jest potomkiem używam tylko reprezentację ciąg jego klucz. Na przykład mam key_str - argument z żądaniem usunięcia instancji ':

instance = Kind.get(key_str) 
instance.delete() 
0

Moje rozwiązanie używa urlsafe aby uzyskać pozycję bez obaw o dominującej ID:

pk = ndb.Key(Product, 1234) 
usafe = LocationItem.get_by_id(5678, parent=pk).key.urlsafe() 
# now can get by urlsafe 
item = ndb.Key(urlsafe=usafe) 
print item 
Powiązane problemy