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

私が知る限り、2 つのライブラリは異なるバージョンの proto を使用していますが、渡されるデータは非常にています...

4

1 に答える 1

3

これは、ndb ライブラリの使用に関する微妙なバグです。

すべての ndb プロパティは、データストア内のプロパティの名前を指定する単一の位置引数を受け入れます

モデル定義を見ると、 が表示されますuser = ndb.KeyProperty('User')。これは実際には、userプロパティがエンティティのキ​​ーであると言っているのではなくUser、プロパティ名で Datastore に格納する必要があることを示していますUser。これは、プロパティ名が (casesensitive) である gae プロトコル バッファ クエリで確認できますUser

キーの種類を 1 つに制限する場合は、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 に答える