7

Jestem w trakcie pisania mojej pierwszej usługi RESTful Web w środowisku GAE i środowiska wykonawczego Python 2.7; Zacząłem od używania nowego, ndb API Guido.Po otrzymaniu odsyłaczy nieznanych rodzajów w NDB

Nie jestem jednak pewien, jak rozwiązać konkretny przypadek bez domyślnej funkcji odsyłacza wstecznego oryginalnego interfejsu API bazy danych. Jeśli użytkownik-agent zwraca szczególną zasobów i te zasoby 1 stopień usunięte:

host/api/rodzaj/id głębokość = 2

Jaki jest najlepszy sposób, aby odkryć powiązany zbiór podmiotów z " jeden "w relacji jeden do wielu, zważywszy, że rodzaj pokrewnego podmiotu jest nieznany w czasie rozwoju?

  • jestem w stanie użyć kwerendy zastępczej jak opisano w previous SO inquiry z powodu tego ostatniego ograniczeń. Fakt, że mój model jest definiowalny w czasie wykonywania (a zatem nie jest na sztywno zakodowany) uniemożliwia mi użycie kwerendy do filtrowania właściwości dla pasujących kluczy.

  • Ancestor i inne bezinteresowne zapytania są również obecnie niedostępne z powodu ograniczenia magazynu danych, które uniemożliwia mi filtrowanie właściwości bez określonego rodzaju.

dotąd jedyny pomysł miałem (poza powracanie do API dB) jest użycie transakcji cross-grupy, aby napisać własny odniesienia na „jeden”, albo poprzez aktualizowanie NDB. StringProperty (repeat = True) zawierające wszystkie powiązane rodzaje, gdy wprowadzany jest element nowego rodzaju, lub po prostu utrzymywanie listy kluczy w "jednym" ndb.KeyProperty (repeat = True) za każdym razem, gdy powiązany "wiele" obiekt jest napisane do magazynu danych.

Mam nadzieję, że ktoś bardziej doświadczony niż ja może zaproponować lepsze podejście.

Biorąc sugestia jmort253 jest, postaram się poszerzyć moje pytanie o konkretny przykład zaadaptowanej z docs:

class Contact(ndb.Expando): 
    """ The One """ 

    # basic info 
    name = ndb.StringProperty() 
    birth_day = ndb.DateProperty() 

    # If I were using db, a collection called 'phone_numbers' would be implicitly 
    # created here. I could use this property to retrieve related phone numbers 
    # when this entity was queried. Since NDB lacks this feature, the service 
    # will neither have a reference to query nor the means to know the 
    # relationship exists in the first place since it cannot be hard-coded. The 
    # data model is extensible and user-defined at runtime; most relationships 
    # will be described only in the data, and must be discoverable by the server. 
    # In this case, when Contact is queried, I need a way to retrieve the 
    # collection of phone numbers. 

    # Company info. 
    company_title = ndb.StringProperty() 
    company_name = ndb.StringProperty() 
    company_description = ndb.StringProperty() 
    company_address = ndb.PostalAddressProperty() 

class PhoneNumber(ndb.Expando): 
    """ The Many """ 

    # no collection_name='phone_numbers' equivalent exists for the key property 
    contact = ndb.KeyProperty(kind='Contact') 
    number = ndb.PhoneNumberProperty() 
+0

Witam, czy możesz pokazać przykład, aby nieco lepiej zrozumieć problem. Wiele osób jest wizualnych, więc widzenie może pomóc ci wyjaśnić twoje pytanie. Powodzenia!:) – jmort253

+0

Jeśli nie wiesz, jakiego rodzaju podmiotu szukasz, co zrobisz z nim/nimi po ich pobraniu? –

+0

Warstwa usługowa po prostu przekształci szereg powiązanych z nią encji, które odkrył, w reprezentację JSON jednostki jawnie żądanej. Od aplikacji klienckiej zależy sposób ich użycia; serwer nie dba o to. – yo22arian

Odpowiedz

8

Interesujące pytanie! Więc zasadniczo chcesz spojrzeć na klasę Contact i dowiedzieć się, czy istnieje jakaś inna klasa modelu, która odwołuje się do KeyProperty; w tym przykładzie PhoneNumber (ale może być ich wiele).

Myślę, że rozwiązaniem jest poproszenie użytkowników o bezpośrednie dodanie tego linku po utworzeniu klasy PhoneNumber.

Możesz to ułatwić swoim użytkownikom, podając im podklasę KeyProperty, która się tym zajmuje; na przykład

class LinkedKeyProperty(ndb.KeyProperty): 
    def _fix_up(self, cls, code_name): 
     super(LinkedKeyProperty, self)._fix_up(cls, code_name) 
     modelclass = ndb.Model._kind_map[self._kind] 
     collection_name = '%s_ref_%s_to_%s' % (cls.__name__, 
               code_name, 
               modelclass.__name__) 
     setattr(modelclass, collection_name, (cls, self)) 

Dokładnie jak wybrać nazwę dla gromadzenia i przechowywania wartości nie jest do ciebie; po prostu umieść tam coś, co ułatwia powrót do linku. Przykładem może stworzyć nowy atrybut na adres:

Contact.PhoneNumber_ref_contact_to_Contact == (PhoneNumber, PhoneNumber.contact) 

[edytowane aby działający kod i dodać przykład. :-)]

+0

Wielkie dzięki za wpis, a jeszcze więcej za niezamówione opracowanie. B) Twoje streszczenie problemu jest spot-on. Wydaje się to również właściwym podejściem. Powoli zaczynam rozumieć mechanikę, która za tym stoi, kiedy przeszukuję źródło pakietu; jednak self._kind, który odpowiada kwarg przekazanej do konstruktora LinkedKeyProperty (kind = 'Contact'), z jakiegoś powodu nie istnieje na mapie rodzajowej - przynajmniej nie w mojej implementacji. W przypadku przykładu zakładam, że powinno to być odwołanie do modelu Contact. – yo22arian

+0

'ndb.Model._kind_map [self._kind] == * crash *' – yo22arian

+0

Jeśli napiszesz LinkedKeyProperty dokładnie tak, jak pokazałem, powinno działać. Być może nie wywodziłeś go z ndb.KeyProperty? Lub nie zrobiłeś najpierw połączenia super()? Jeśli nie możesz go uruchomić, pokaż pełny kod, który wypróbowałeś, i pełne informacje zwrotne. –

2

brzmi jak dobry przypadku wykorzystania do ndb.StructuredProperty.

+1

Dzięki za sugestię! Jednak ndb.StructuredProperty ma w moim przypadku ograniczenie dyskwalifikujące: "nie można go odzyskać niezależnie od podmiotu Kontakt, do którego należy". – yo22arian

Powiązane problemy