Google app engine ndb建模
我是ndb的新手。我的结构大体上是这样的:Google app engine ndb建模,google-app-engine,app-engine-ndb,Google App Engine,App Engine Ndb,我是ndb的新手。我的结构大体上是这样的: a = [b, c] b = [d, e, f] d = [g, h] e = [k, l, m, n] f = [o] c = [p, r, t] 我有下面的型号 class Child(ndb.Model): name = ndb.StringProperty() child = ndb.KeyProperty(kind="Child", repeated=True) class Root(ndb.Model): nam
a = [b, c]
b = [d, e, f]
d = [g, h]
e = [k, l, m, n]
f = [o]
c = [p, r, t]
我有下面的型号
class Child(ndb.Model):
name = ndb.StringProperty()
child = ndb.KeyProperty(kind="Child", repeated=True)
class Root(ndb.Model):
name = ndb.StringProperty()
child = db.StructuredProperty(Child, repeated=True)
我不能这样做,因为ndb不允许我重复,因为我已经重复了
对该结构建模的正确方法是什么?如果您只想在单个“根”上存储多个“子”实体,则可以使用
LocalStructuredProperty
来包含子
模型(但这意味着它不会被索引)。在讨论嵌套的结构化属性时,中有一个关于此行为的提示:
尽管StructuredProperty可以重复,StructuredProperty可以包含另一个StructuredProperty,但请注意:如果一个结构化属性包含另一个,则只能重复其中一个。解决方法是使用LocalStructuredProperty,它没有此约束(但不允许查询其属性值)
对嵌套关系建模的另一个选项是在键上使用祖先。例如,假设您的根密钥路径是:('Root',1)
。您可以使用键('Root',1',Child',1)
,('Root',1',Child',5)
,等等在其下方添加子项,每次都将“Child”附加到键路径。然后,我们希望查询对象的子对象,您可以使用祖先查询,例如:
def create_child(parent, name):
new_child = Child(parent=parent.key, name=name)
new_child.put()
return new_child
def get_children(parent):
return Child.query(ancestor=parent.key)
class Child(ndb.Model):
name = ndb.StringProperty()
class Root(ndb.Model):
name = ndb.StringProperty()
在这一点上,您甚至不再需要根目录
,因为您可以分配任意键路径,也可以使用名称
作为ID,并存储较少的信息
这就是说,它实际上完全取决于您实际尝试建模的内容,这里没有足够的信息来理解您的意思。如果您只想在一个“根”上存储多个“子”实体,您可以使用
LocalStructuredProperty
来包含子
模型(但这意味着它不会被索引)。在讨论嵌套结构化属性时,中有一个关于此行为的提示:
尽管StructuredProperty可以重复,StructuredProperty可以包含另一个StructuredProperty,但请注意:如果一个结构化属性包含另一个,则只能重复其中一个。解决方法是使用LocalStructuredProperty,它不具有此约束(但不允许查询其属性值)
类似这样的嵌套关系建模的另一个选项是在键上使用祖先。例如,假设您的根键路径是:('Root',1)
。您可以使用键('Root',1',Child',1)
,('Root',1',Child',5)在其下方添加子项
,依此类推,每次都将“Child”附加到密钥路径。然后,如果您想查询对象的子对象,可以使用祖先查询,例如:
def create_child(parent, name):
new_child = Child(parent=parent.key, name=name)
new_child.put()
return new_child
def get_children(parent):
return Child.query(ancestor=parent.key)
class Child(ndb.Model):
name = ndb.StringProperty()
class Root(ndb.Model):
name = ndb.StringProperty()
此时您甚至不需要有Root
了,因为您可以分配任意的键槽,也可以使用name
作为ID,并存储较少的信息
也就是说,它实际上完全取决于您实际尝试建模的内容,这里没有足够的信息来理解您的意思。我不明白您为什么需要在孩子身上使用
KeyProperty
。您可以这样建模您的关系:
class Child(ndb.Model):
name = ndb.StringProperty()
class Root(ndb.Model):
name = ndb.StringProperty()
child = ndb.KeyProperty(repeated=True)
c1 = Child(name="b").put()
c2 = Child(name="c").put()
a = Root(child=[c1,c2]).put() # put returns the key; otherwise you would need c1.key() here
children_keys = a.get().child # [Key(Child, 1234), Key(Child, 4567)]
# to retrieve the children, you could do
children = [ key.get() for key in children_keys ]
我不明白为什么您需要在孩子身上使用
KeyProperty
。您可以这样对您的关系进行建模:
class Child(ndb.Model):
name = ndb.StringProperty()
class Root(ndb.Model):
name = ndb.StringProperty()
child = ndb.KeyProperty(repeated=True)
c1 = Child(name="b").put()
c2 = Child(name="c").put()
a = Root(child=[c1,c2]).put() # put returns the key; otherwise you would need c1.key() here
children_keys = a.get().child # [Key(Child, 1234), Key(Child, 4567)]
# to retrieve the children, you could do
children = [ key.get() for key in children_keys ]
请记住几件事。假设您将记录想象成文件系统中的文件
- KeyProperty是指向另一个文件的指针
- 重复属性仅存储多个值
- 在本例中根本没有理由使用结构化属性,所以让我们跳过它
class Node(ndb.Model):
parent = ndb.KeyProperty(kind='Node')
def get_children(self):
return Node.query().filter(Node.parent == self.key)
您可以使用get_children来获取任何节点的子节点。请注意,这部分最终是一致的,因此最近添加的节点通常不会在get_children中显示一秒钟左右
root = Node(parent=None)
child1 = Node(parent=root)
child2 = Node(parent=root)
child3 = Node(parent=root)
sub_child1 = Node(parent=child1)
请记住几件事。假设您将记录想象成文件系统中的文件
- KeyProperty是指向另一个文件的指针
- 重复属性仅存储多个值
- 在本例中根本没有理由使用结构化属性,所以让我们跳过它
class Node(ndb.Model):
parent = ndb.KeyProperty(kind='Node')
def get_children(self):
return Node.query().filter(Node.parent == self.key)
您可以使用get_children来获取任何节点的子节点。请注意,这部分最终是一致的,因此最近添加的节点通常不会在get_children中显示一秒钟左右
root = Node(parent=None)
child1 = Node(parent=root)
child2 = Node(parent=root)
child3 = Node(parent=root)
sub_child1 = Node(parent=child1)
由于根类型和子类型的实体几乎相同,我看到您尝试建模的数据是同类实体之间一对多关系的经典示例。此类关系的建模如下:
class RelatedKind(ndb.Model):
name = ndb.StringProperty()
root = ndb.KeyProperty(kind="RelatedKind")
要创建实体,请执行以下操作:
a = RelatedKind(name='a')
a_key = a.put()
b = RelatedKind(name='b', root=a_key)
b_key = b.put()
c = RelatedKind(name='c', root=a_key)
c_key = c.put()
# To get all 'child' of a;
child_a = RelatedKind.query(root == a_key).fetch()
print(child_a)
# >>> [b_key, c_key]
使用数据存储查询和keyproperty,您可以实现相同的建模,而无需重复使用。由于根类型和子类型的实体几乎相同,我看到您尝试建模的数据是同类实体之间一对多关系的经典示例。modellin