了解ndb密钥类与KeyProperty

时间:2013-04-15 16:55:42

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

我查看了文档,文档和SO问题和答案,并且仍在努力理解其中的一小部分内容。您应该选择哪个以及何时选择?

这是我到目前为止所读到的(只是样本):

关键课对我来说似乎很简单。当您创建一个ndb实体时,数据存储区会自动为您创建一个键,通常以key(Kind,id)的形式为您创建id。

所以说你有这两个模型:

class Blah(ndb.Model):
     last_name = ndb.StringProperty()

class Blah2(ndb.Model):
     first_name = ndb.StringProperty()
     blahkey = ndb.KeyProperty()

所以只使用密钥类型,你想让Blah1成为父母(或者有几个姓氏相同的家庭成员)

lname = Blah(last_name = "Bonaparte")
l_key = lname.put() **OR**
l_key = lname.key.id() # spits out some long id 

fname_key = l_key **OR**
fname_key = ndb.Key('Blah', lname.last_name) # which is more readable.. 

然后:

lname = Blah2( parent=fname_key, first_name = "Napoleon")
lname.put()

lname2 = Blah2( parent=fname_key, first_name = "Lucien")
lname2.put()

到目前为止一切顺利(我认为)。现在关于Blah2的KeyProperty。假设Blah1仍然是相同的。

lname3 = Blah2( first_name = "Louis", blahkey = fname_key)
lname3.put()

这是对的吗?

如何查询各种内容

查询姓氏:

Blah.query() # all last names
Blah.query(last_name='Bonaparte') # That specific entity.

名字:

Blah2.query()
napol =   Blah2.query(first_name = "Napoleon")
bonakey = napol.key.parent().get() # returns Bonaparte's key ??

bona = bonakey.get() # I think this might be redundant

这是我迷路的地方。如何使用key或keyproperty从名字中查找Bonaparte。我没有在这里添加它,也许应该有,这是父母,祖父母,伟大的父母的讨论,因为Keys跟踪祖先/父母。

您如何以及为何使用KeyProperty与固有密钥类。还想象你有3个传感器s1,s2,s3。每个传感器都有成千上万的读数,但是你想保持与s1相关的读数,这样你就可以用s1表示今天的所有读数。你会用哪个? KeyProperty还是关键类?如果在其他地方已经回答这个问题,我很抱歉,但我没有看到关于选择哪个以及为什么/如何做出明确的示例/指南。

2 个答案:

答案 0 :(得分:2)

我认为混淆来自使用密钥。密钥不与实体内的任何属性相关联,它只是定位单个实体的唯一标识符。它可以是数字或字符串。

幸运的是,除了这一行之外,你的所有代码看起来都很好:

fname_key = ndb.Key('Blah', lname.last_name) # which is more readable.. 

构造一个Key需要一个唯一的ID,它与一个属性不同。也就是说,它不会将变量lname.last_name与属性last_name相关联。相反,您可以像这样创建记录:

lname = Blah(id = "Bonaparte")
lname.put()
lname_key = ndb.Key('Blah', "Bonaparte")

您可以保证只有一个具有该ID的Blah实体。实际上,如果使用类似last_name的字符串作为ID,则无需将其存储为单独的属性。将实体ID视为唯一的额外字符串属性。

接下来,请注意不要认为Blah.last_name和Blah2.first_name在您的查询中是唯一的:

lname = Blah2( parent=fname_key, first_name = "Napoleon")
lname.put()

如果您多次执行此操作,将会有多个具有第一个拿破仑名称的实体(所有实体都具有相同的父键)。

继续上面的代码:

napol =   Blah2.query(first_name = "Napoleon")
bonakey = napol.key.parent().get() # returns Bonaparte's key ??
bona = bonakey.get() # I think this might be redundant

napol包含查询,而不是结果。您需要调用napol.fetch()来获取所有带有“Napolean”的实体(如果您确定只有一个实体,则为napol.get())。 bonakey是相反的,由于get()而不是Bonaparte的密钥,它保存父实体。如果您关闭了.get(),那么bona将正确拥有父级。

最后,关于传感器的问题。您可能不需要KeyProperty或“固有”键。如果您有这样的读物类:

class Readings(ndb.Model):
    sensor = ndb.StringProperty()
    reading = ndb.IntegerProperty()

然后你可以将它们全部存储在没有键的单个表中。 (您可能希望包含时间戳或其他属性。)稍后,您可以使用此查询检索:

s1_readings = Readings.query(Readings.sensor == 'S1').fetch()

答案 1 :(得分:1)

我也是NDB的新手,我现在仍然不了解所有内容,但我认为当您使用 Napoleon 的父级创建 Blah2 时,你需要父母查询它或不会出现。例如:

napol = Blah2.query(first_name = "Napoleon")

不会得到任何东西(并且您没有使用正确的NDB格式),但使用父代将执行:

napol = Blah2.query(ancestor=fname_key).filter(Blah2.first_name == "Napoleon").get

不知道这是否为你的问题提供了一些启示。