在 gcloud api 中按键查询 google 数据存储

Query google datastore by key in gcloud api

我正在尝试使用我刚刚发现的 gcloud api 查询一些数据。我想查询 KeyPropery。例如:

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, :classdatetime.datetime) – The value to filter on.

是否可以为关键属性添加过滤器?


我做了更多的调查,试图找出这里到底发生了什么。我不确定这对我目前理解这个问题是否有帮助,但也许对其他人有帮助。

我模拟了各个库中的底层调用,以记录正在序列化并发送到服务器的协议缓冲区。对于 GAE,它似乎是 datastore_query 模块中的 Batch.create_async

对于gcloud,就是datastore.Client.connection.run_query方法。查看生成的协议缓冲区(匿名),我看到:

gcloud 查询 pb.

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"
            }
          }
        }
      }
    }
  }
}

GAE 查询 pb。

kind: "Data"
Filter {
  op: 5
  property <
    name: "User"
    value <
      ReferenceValue {
        app: "s~app-id"
        PathElement {
          type: "User"
          name: "user_string_id"
        }
      }
    >
    multiple: false
  >
}

据我所知,这两个库使用了不同版本的原型,但传递的数据看起来非常相似...

这是您使用 ndb 库时的一个细微错误:

All ndb properties accept a single positional argument that specifies the property's name in Datastore

查看您的模型定义,您会看到 user = ndb.KeyProperty('User')。这实际上并不是说 user 属性 是 User 实体的键,而是它应该以 属性 名称 User 存储在 Datastore 中].您可以在 属性 名称(区分大小写)User.

的 gae 协议缓冲区查询中验证这一点

如果要将密钥限制为单一种类,则需要使用 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)