Следующие обратные ссылки неизвестных видов в НБД

Я нахожусь в процессе написания моего первого веб-сервиса RESTful поверх GAE и среды выполнения Python 2.7; Я начал использовать блестящий новый API ndb от Guido.

Однако я не уверен, как решить конкретный случай без неявной функции обратной ссылки исходного API базы данных. Если пользовательский агент запрашивает определенный ресурс и эти ресурсы удалены на 1 градус:

хост / API / тип / идентификатор? Глубина = 2

What's the best way to discover a related collection of entities from the "one" in a one-to-many relationship, given that the kind of the related entity is unknown at development time?

I'm unable to use a replacement query as described in a previous SO inquiry due to the latter restriction. The fact that my model is definable at runtime (and therefore isn't hardcoded) prevents me from using a query to filter properties for matching keys.

Ancestor and other kindless queries are also out due to the datastore limitation that prevents me from filtering on a property without the kind specified.

До сих пор единственная идея, которую я имел (помимо возврата к API db), состоит в том, чтобы использовать транзакцию между группами для записи моей собственной ссылки на "one", либо путем обновления ndb.StringProperty (repeat = True) содержащий все связанные виды, когда вводится сущность нового вида, или просто ведение списка ключей на «одном» ndb.KeyProperty (repeat = True) каждый раз, когда связано "много" сущность записывается в хранилище данных.

Я надеюсь, что кто-то более опытный, чем я, может предложить лучший подход.

Учитывая предложение jmort253, я попытаюсь дополнить мой вопрос конкретным примером, адаптированным из документов:

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()
 jmort25324 мая 2012 г., 07:12
Привет, вы можете показать пример, чтобы помочь понять проблему немного лучше. Многие люди визуальны, поэтому зрение может помочь прояснить ваш вопрос. Удачи! :)
 yo22arian25 мая 2012 г., 17:12
Сервисный уровень просто сериализует связанные сущности, которые он обнаружил, в JSON-представление явно запрашиваемой сущности. Это зависит от клиентского приложения, чтобы определить, как они используются; сервер не заботится.
 Nick Johnson25 мая 2012 г., 08:12
Если вы не знаете, какую сущность вы ищете, что вы будете делать с ней / ними, когда получите их?

Ответы на вопрос(2)

 yo22arian24 мая 2012 г., 20:16
Спасибо за предложение! Однако в моем случае ndb.StructuredProperty имеет свое собственное дисквалифицирующее ограничение: его «нельзя извлечь независимо от объекта« Контакт », к которому [он] принадлежит».
Решение Вопроса

в основном вы хотите взглянуть на класс Contact и выяснить, есть ли другой класс модели, на который ссылается KeyProperty; в этом примере PhoneNumber (но их может быть много).

Я думаю, что решение состоит в том, чтобы попросить ваших пользователей явно добавить эту ссылку при создании класса PhoneNumber.

Вы можете упростить это для своих пользователей, предоставив им подкласс KeyProperty, который позаботится об этом; например

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))

Как именно вы выбираете имя для коллекции и ценность для хранения там зависит от вас; просто поместите туда что-нибудь, что облегчит вам переход по ссылке назад. В примере будет создан новый атрибут для контакта:

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

[отредактировано, чтобы сделать код работающим и добавить пример. :-)]

 29 мая 2012 г., 19:30
Отлично, так что, возможно, вы можетеaccept ответ?
 yo22arian26 мая 2012 г., 11:03
ndb.Model._kind_map[self._kind] == *crash*
 yo22arian29 мая 2012 г., 11:47
Работает отлично. Ошибка была явно моей, возникшей из-за необъяснимого изменения состояния приложения, которое не имело никакого отношения к источнику. Я пытался воспроизвести эту ошибку несколько раз в поисках лучшего объяснения, но пришел к выводу, что лучше всего потратить время на то, чтобы заставить работать новые функции, а не объяснять, почему это не так.
 29 мая 2012 г., 06:06
Если вы напишите LinkedKeyProperty именно так, как я показал, он должен работать. Возможно, вы не получили его от ndb.KeyProperty? Или вы сначала не сделали вызов super ()? Если вы не можете заставить его работать, пожалуйста, покажите полный код, который вы пробовали, и полную обратную трассировку.
 yo22arian26 мая 2012 г., 11:02
Большое спасибо за пост, и даже больше за нежелательную разработку. Б) Ваш краткий обзор проблемы точен. Это также кажется правильным подходом. Я медленно начинаю понимать механику, лежащую в основе этого, когда я прочесываю источник пакета; однако self._kind, который соответствует kwarg, переданному конструктору LinkedKeyProperty (kind = 'Contact'), по какой-то причине не существует на карте вида - по крайней мере, в моей реализации. В случае примера, я предполагаю, что это должно быть извлечение ссылки на модель контакта.

Ваш ответ на вопрос