如何使用实体键在GQL中查询

75
我如何在Google App Engine数据查看器中使用GQL针对实体键编写查询?
在查看器中,第一列(Id / Name)显示为name=_1,在详细视图中,它会显示密钥。
Decoded entity key: Programme: name=_1
Entity key: agtzcG9................... 

这个查询无法正常工作:

SELECT * FROM Programme where name = '_1'
5个回答

109
您可以使用实体的键来检索它:
SELECT * FROM Programme where __key__ = KEY('agtzcG9...................')

而且,您应该能够类似地使用名称进行查询:

SELECT * FROM Programme where __key__ = KEY(Programme, '_1')

请注意,在您的AppEngine应用程序中不建议这样做;正如Nick在他的评论中指出的那样,这是一种极大的时间浪费。实际上,这个例子只是为了向您展示如何在管理控制台中按键查询。


4
啊,不行。这将是一个巨大的时间和资源浪费。 - Nick Johnson
4
@Nick:但在管理员控制台中,可能没有更好的方法。 - Thilo
4
可以通过ID而不是键进行查询吗? - tensaix2j
请记住,如果 ID 是字符串,则需要将其引用。 如果是数字,则不应将其引用。 因此,如果 ID 是一个数值类型,值为 888,则上述查询语句应该是:SELECT * FROM Programme WHERE key = KEY('Programme', 888)。 - Ezward
计数实际上是一项昂贵的操作,为了查看实体是否存在,我只需查询它并获取第一个结果。 - ZiglioUK
显示剩余2条评论

20
对于数字ID,类似于按名称查询的形式可以使用:
SELECT * from Programme where __key__ = KEY('Programme', 1234567)
我发现这个表单在管理控制台中特别有用。

18

您完全不需要查询即可通过键获取实体 - 您可以直接按键提取实体。在Python中,您可以使用MyModel.get_by_key_name('_1')来实现这一点。这比Adam建议的使用查询快3到5倍。


5
不是我建议的,Nick,我只是想帮他让他的查询工作。我认为他试图在管理员控制台数据查看器中查看东西。 - Adam Crossland
@Nick+Adam:是的,我正在尝试在管理控制台中查看一些数据。 - Thilo
1
就记录而言,__key__查询通常直接从实体表本身读取,而不是先从索引读取再从实体表读取。因此,在实际操作中,当数据存储将此查询编译为原始的Bigtable查找或扫描时,__key__ ==查询和get()之间没有太大区别。当然,这是一个实现细节。但在查找单个实体时,使用get()仍然是一个好的做法。 - ryan
Ryan,__key__查询从未从实体表中读取。它们从索引表中读取,包括所有表,但不包括实体表;索引表都指向一个键,因此无论您使用哪个索引来搜索,都是从那里获取您的键。在1.6.5中,有投影查询可以实际读取键和匹配的索引数据,价格与键查询相同... ...也就是说,您永远不必对实体表施加争用。 - Ajax
2
@Ajax 交叉线路。Ryan 谈论的是形如 "SELECT * FROM Kind WHERE key = :1" 的查询;而你谈论的是形如 "SELECT key FROM Kind ..." 的查询。你们各自关于查询类型的说法都是正确的。 - Nick Johnson

3

在按键查询时,您需要精确匹配键,包括父级而不仅仅是ID或名称。当然,如果父级为null,就像上面的例子一样,ID或名称以及实体类型就足够了。

如果您已经编码了实体键,则可以直接使用它:

SELECT * FROM Programme where __key__ = KEY('agtzcG9...................')

对于上面的简单示例,

SELECT * FROM Programme where __key__ = KEY('Programme', '_1')

会做,但如果您的键有一个父级,比如
Paren: id=123

然后查询将会是什么?
SELECT * FROM Programme where __key__ = KEY('Paren', 123, 'Programme', '_1')

如果父级本身有一个父级,您也需要将其添加到其中。更多详情请参见官方GQL文档
似乎没有办法选择具有相同ID或名称但不考虑其父级的所有内容。

1

关于这个问题,我想简单说明一下:当我在KEY中使用任何引号时,调用会失败(在管理控制台中,我会收到错误弹窗)。

例如,对于类型为“mytype”,ID/名称为12345,以下内容不起作用

SELECT * FROM mytype WHERE __key__ = KEY('mytype', '12345')

但这个会:

SELECT * FROM mytype WHERE __key__ = KEY(mytype, 12345)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接