追溯NDB中的未知种类 [英] Following backreferences of unknown kinds in NDB
问题描述
我正在编写GAE和Python 2.7运行时的第一个RESTful Web服务;我已经开始使用Guido的闪亮的新的ndb API。然而,我不确定如何解决一个特定的情况,没有原始数据库的隐式反向引用特性API。如果用户代理请求特定的资源并删除1度的资源:
host / api / kind / id?depth = 2
考虑到在开发时相关实体的类型是未知的,在一对多关系中发现一个相关实体集合的最好方法是什么?
-
我无法使用以前的SO查询。事实上,我的模型在运行时是可定义的(因此没有硬编码),这使我无法使用查询来过滤匹配键的属性。
祖先和其他无情的查询也由于数据存储区限制而无法使用,这些限制阻止了我在没有指定类型的情况下对属性进行过滤。 >到目前为止,我唯一的想法(除了恢复到db api之外)是使用跨组事务在one上编写自己的引用,或者通过更新ndb.StringProperty(repeat = True)当引入新类型的实体时包含所有相关类型,或者每次将相关的many实体写入数据存储时,通过简单地在onendb.KeyProperty(repeat = True)上维护一个键列表。 / p>
我希望有人比我更有经验可以提出更好的方法。
鉴于jmort253的建议,我会用一个具体的例子来改进我的问题文档:
$ $ p $ class Contact(ndb.Expando):
The One
#基本信息
名字= ndb.StringProperty()
birth_day = ndb.DateProperty()
#如果我使用db,一个名为'phone_numbers '会隐式地在这里创建
#。我可以在查询此实体时使用此属性检索相关电话号码
#。由于NDB缺乏这种功能,服务
#既不会有查询的引用,也无法知道
#关系,因为它不能被硬编码。
#数据模型在运行时是可扩展的和用户定义的;大多数关系
#将仅在数据中描述,并且必须由服务器发现。
#在这种情况下,当查询联系人时,我需要一种方法来检索
#电话号码集合。
#公司信息。
company_title = ndb.StringProperty()
company_name = ndb.StringProperty()
company_description = ndb.StringProperty()
company_address = ndb.PostalAddressProperty()
class PhoneNumber(ndb.Expando):
Many
#no collection_name ='phone_numbers'等同于键属性
contact = ndb .KeyProperty(kind ='Contact')
number = ndb.PhoneNumberProperty()
有趣的问题!所以基本上你想看看Contact类,看看是否有其他的模型类有一个KeyProperty引用它;在这个例子中PhoneNumber(但可能有很多)。
我认为解决方案是让你的用户在创建PhoneNumber类时显式地添加这个链接。
p>通过为用户提供一个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)
I'm in the process of writing my first RESTful web service atop GAE and the Python 2.7 runtime; I've started out using Guido's shiny new ndb API.
However, I'm unsure how to solve a particular case without the implicit back-reference feature of the original db API. If the user-agent requests a particular resource and those resources 1 degree removed:
host/api/kind/id?depth=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.
Thus far, the only idea I've had (beyond reverting to the db api) is to use a cross-group transaction to write my own reference on the "one", either by updating an ndb.StringProperty(repeat=True) containing all the related kinds when an entity of a new kind is introduced or by simply maintaining a list of keys on the "one" ndb.KeyProperty(repeat=True) every time a related "many" entity is written to the datastore.
I'm hoping someone more experienced than myself can suggest a better approach.
Given jmort253's suggestion, I'll try to augment my question with a concrete example adapted from the 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()
Interesting question! So basically you want to look at the Contact class and find out if there is some other model class that has a KeyProperty referencing it; in this example PhoneNumber (but there could be many).
I think the solution is to ask your users to explicitly add this link when the PhoneNumber class is created.
You can make this easy for your users by giving them a subclass of KeyProperty that takes care of this; e.g.
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))
Exactly how you pick the name for the collection and the value to store there is up to you; just put something there that makes it easy for you to follow the link back. The example would create a new attribute on Contact:
Contact.PhoneNumber_ref_contact_to_Contact == (PhoneNumber, PhoneNumber.contact)
[edited to make the code working and to add an example. :-) ]
这篇关于追溯NDB中的未知种类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!