在gcloud api

时间:2016-03-16 22:03:40

标签: python google-cloud-datastore app-engine-ndb gcloud-python google-cloud-python

我尝试使用我刚刚发现的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方法。查看生成的协议缓冲区(匿名),我看到:

gcloud query 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
  >
}

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

1 个答案:

答案 0 :(得分:3)

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

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

查看您的模型定义,您会看到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)