我尝试使用我刚刚发现的gcloud
api查询某些数据。我想查询KeyPropery
。 e.g:
from google.appengine.ext import ndb
class User(ndb.Model):
email = ndb.StringProperty()
class Data(ndb.Model):
user = ndb.KeyProperty('User')
data = ndb.JsonProperty()
在GAE中,假设我有一个用户密钥,我可以很容易地查询:
user = User.query(User.email == 'me@domain.com').get()
data_records = Data.query(Data.user == user.key).fetch()
我想使用gcloud
:
from gcloud import datastore
client = datastore.Client(project='my-project-id')
user_qry = client.query(kind='User')
user_qry.add_filter('email', '=', 'me@domain.com')
users = list(user_qry.fetch())
user = users[0]
data_qry = client.query(kind='Data')
data_qry.add_filter('user', '=', user.key) # This doesn't work ...
results = list(data_qry.fetch()) # results = []
查看add_filter
的文档,Entity.key
只是supported type并不显示
value(int,str,bool,float,NoneType,:class
datetime.datetime
) - 要过滤的值。
是否可以为关键属性添加过滤器?
我已经做了更多的调查,试图弄清楚这里到底发生了什么。我不确定这对我目前理解这个问题是否有帮助,但也许对其他人有帮助。
我嘲笑了各个库中的底层调用,以记录正在序列化并发送到服务器的协议缓冲区。对于GAE,它在datastore_query模块中似乎是Batch.create_async
。
对于gcloud
,它是datastore.Client.connection.run_query
方法。查看生成的协议缓冲区(匿名),我看到:
kind {
name: "Data"
}
filter {
composite_filter {
operator: AND
filter {
property_filter {
property {
name: "user"
}
operator: EQUAL
value {
key_value {
partition_id {
dataset_id: "s~app-id"
}
path_element {
kind: "User"
name: "user_string_id"
}
}
}
}
}
}
}
kind: "Data"
Filter {
op: 5
property <
name: "User"
value <
ReferenceValue {
app: "s~app-id"
PathElement {
type: "User"
name: "user_string_id"
}
}
>
multiple: false
>
}
据我所知,这两个库正在使用不同版本的proto,但传递的数据看起来非常相似......
答案 0 :(得分:3)
这是您使用ndb库时的一个微妙错误:
查看您的模型定义,您会看到user = ndb.KeyProperty('User')
。实际上并不是说user
属性是User
实体的密钥,而是应该将其存储在属性名为User
的数据存储区中。您可以在gae协议缓冲区查询中验证此属性名称是(区分大小写)User
。
如果要将密钥限制为单一类型,则需要使用kind选项指定它。
user = ndb.KeyProperty(kind="User")
KeyProperty
也支持:
user = ndb.KeyProperty(User) # User is a class here, not a string
Here is a description of all the magic
就像现在一样,你的gcloud查询正在查询错误的用户,应该是:
data_qry = client.query(kind='Data')
data_qry.add_filter('User', '=', user.key)