5

I've looked through the documentation, the docs and SO questions and answers and am still struggling with understanding a small piece of this. Which should you choose and when?

This is what I've read so far (just sample):

The key class seems pretty straightforward to me. When you create an ndb entity the datastore automatically creates for you a key usually in the form of key(Kind, id) where the id is created for you .

So say you have these two models:

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

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

So just using the key kind and you want to make Blah1 a parent (or have several family members with the same last name)

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.. 

then:

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

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

So far so good (I think). Now about the KeyProperty for Blah2. Assume Blah1 is still the same.

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

Is this correct ?

How to query various things

Query Last Name:

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

First Name:

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

this is where I get lost. How to look for Bonaparte from first name by using either key or keyproperty. I didn't add it here and perhaps should have and that is the discussion of parents, grand parents, great grand parents since Keys keep track of ancestors/parents.

How and why would you use KeyProperty vs the inherent key class. Also imagine you had 3 sensors s1, s2, s3. Each sensor had thousands of readings but you want to keep readings associated with s1 so that you could graph say All readings for today for s1. Which would you use? KeyProperty or the key class ? I apologize if this has been answered elsewhere but I didn't see a clear example/guide about choosing which and why/how.

4

2 回答 2

2

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

幸运的是,除了这一行之外,您的所有代码看起来都不错:

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()

如果您多次执行此操作,将会有多个 first_name 为 Napoleon 的实体(都具有相同的父键)。

继续上面的代码:

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()
于 2013-05-31T01:07:31.317 回答
1

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

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

不会得到任何东西(并且您没有为 NDB 使用正确的格式),但使用父级会做:

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

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

于 2013-05-30T10:54:22.617 回答