以下是NDB中未知类型的反向引用

时间:2012-05-24 05:03:14

标签: python google-app-engine google-cloud-datastore app-engine-ndb

我正在使用GAE和Python 2.7运行时编写我的第一个RESTful Web服务;我开始使用Guido的闪亮的新ndb API。

但是,如果没有原始db API的隐式反向引用功能,我不确定如何解决特定情况。如果用户代理请求特定资源并且删除了1度的资源:

主机/ API /种类/ ID?深度= 2

考虑到在开发时未知相关实体的类型,从一对多关系中发现“一个”实体的相关集合的最佳方法是什么? < / p>

  • 由于后一种限制,我无法使用previous SO inquiry中所述的替换查询。我的模型在运行时可以定义(因此不是硬编码)的事实使我无法使用查询来过滤匹配键的属性。

  • 由于数据存储限制阻止我在没有指定类型的情况下对属性进行过滤,因此祖先和其他无意义的查询也会被取消。

到目前为止,我所拥有的唯一想法(除了恢复到db api之外)是使用跨组事务在“one”上编写我自己的引用,或者通过更新ndb.StringProperty(repeat = True)包含引入新类型实体时的所有相关类型,或者每次将相关的“many”实体写入数据存储区时,只需在“one”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()

2 个答案:

答案 0 :(得分:8)

有趣的问题!所以基本上你想查看Contact类,看看是否有其他模型类有一个KeyProperty引用它;在这个例子中,PhoneNumber(但可能有很多)。

我认为解决方案是在创建PhoneNumber类时要求您的用户明确添加此链接。

通过为用户提供KeyProperty的子类来处理这个问题,您可以轻松地为用户提供这些功能。 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))

您究竟如何选择集合的名称以及存储的值取决于您;只需放置一些东西,便于您按照链接返回。该示例将在Contact上创建一个新属性:

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

[编辑以使代码正常工作并添加示例。 :-)]

答案 1 :(得分:2)

听起来像是ndb.StructuredProperty的一个很好的用例。