StructuredProperty的重复嵌套属性

时间:2016-01-14 13:22:27

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

虽然NDB文档说:

  

虽然可以重复StructuredProperty并且StructuredProperty可以包含另一个StructuredProperty,但要注意:如果一个结构化属性包含另一个,则只能重复其中一个

在我看来,对文档的最清晰的解释可以正确地写成"如果一个结构化属性包含另一个结构化属性"。

在这种情况下,我希望这样的事情可以发挥作用:

class KeyList(ndb.Model):
  keys = ndb.KeyProperty(repeated=True)

class Collection(ndb.Model):
  lists = ndb.StructuredProperty(KeyList, repeated=True)

然而,这失败并出现错误:

  

TypeError:此StructuredProperty不能使用repeated = True,因为它的模型类(KeyList)包含重复的属性(直接或间接)。

似乎无法在重复的StructuredProperty中嵌套任何重复属性。

从代码中,looks to be the intended behaviour

在这种情况下,开发应用程序服务器可能与记录的行为不同。如果我正在阅读的文档是正确的,那么the condition in the development server giving rise to the above error的修正可能是这样的:

if modelclass._has_repeated and isinstance(modelclass, StructuredProperty):
   # ...

AppEngine StructuredProperty能否包含重复属性(重复的StructuredProperty除外)?

问题报告在此处:https://github.com/GoogleCloudPlatform/appengine-python-vm-runtime/issues/40

编辑值得注意的是golang docs这样说:

  

结构片段是有效的,包含切片的结构也是如此。但是,如果一个结构包含另一个结构,则最多可以重复其中一个结构。这取消了递归定义的结构类型:任何(直接或间接)包含[] T的结构T。

我从中得到的暗示是重复结构的重复非结构属性在BigTable级别并不是固有的禁止,而是Python实现的副作用。

如果没有进一步的佐证,我就不会依赖这种含义。

2 个答案:

答案 0 :(得分:3)

这是我们文档中的错误 -

使用StructuredProperty s,您只能拥有一层重复的属性。

一些背景知识:

ndb在写入数据存储区之前通过爆炸属性来处理StructuredProperty。例如:

class Inner(ndb.Model):
  a = ndb.StringProperty()

class Outer(ndb.Model):
  inner = ndb.StructuredProperty(Inner, repeated=True)

然后,如果我们写:Outer(inner=[Inner(a="1"), Inner(a="2")]),这实际上会被写入数据存储区:

{
  inner.a = ["1", "2"]
}

但是,如果重复Inner.a,我们可以编写如下内容:

 Outer(inner=[Inner(a=["1", "3"]), Inner(a=["2", "4"])])

这将写入数据存储区,如:

{
  inner.a : ["1", "3", "2", "4"]
}

然后当我们读到这篇文章时,我们不知道如何解析,因为所有这些都是有效的:

Outer(inner=[Inner(a=["1", "3"]), Inner(a=["2", "4"])])
Outer(inner=[Inner(a=["1", "3", "2"]), Inner(a=["4"])])
Outer(inner=[Inner(a=["1"]), Inner(a=["3"]), Inner(a=["2"]), Inner(a=["4"])])
Outer(inner=[Inner(a=[]), Inner(a=["1", "3", "2", "4"])])

请注意,其他库(例如Objectify)可以通过存储索引的爆炸属性和整个数据集的未编制索引来避免此问题,该数据集可以维护反序列化的结构。

答案 1 :(得分:-1)

结构化属性的文档明确指出:

  

虽然可以重复StructuredProperty并且StructuredProperty可以包含另一个StructuredProperty,但要注意:如果一个structred属性包含另一个,则只能重复其中一个。解决方法是使用LocalStructuredProperty,它没有此约束(但不允许查询其属性值)。