1

我正在尝试使用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支持的类型

value (int, str, bool, float, NoneType, :class datetime.datetime) -- 要过滤的值。

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


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

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

对于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
  >
}

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

4

1 回答 1

3

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

所有 ndb 属性都接受一个位置参数,该参数指定数据存储区中的属性名称

查看您的模型定义,您会看到user = ndb.KeyProperty('User'). 这实际上并不是说该user属性是User实体的键,而是说它应该使用属性 name 存储在 Datastore 中User。您可以在属性名称为(区分大小写)的 gae 协议缓冲区查询中验证这一点User

如果要将键限制为单一种类,则需要使用 kind 选项指定它。

user = ndb.KeyProperty(kind="User") 

KeyProperty还支持:

user = ndb.KeyProperty(User)   # User is a class here, not a string

这里是对所有魔法的描述

就像现在一样,您的 gcloud 查询正在查询错误的用户,应该是:

data_qry = client.query(kind='Data')
data_qry.add_filter('User', '=', user.key)
于 2016-03-18T16:48:21.403 回答