2009年9月23日水曜日

#appengine で親Keyのみを使ったQueryの動作について

一部修正しました

Kind Indexについて勘違いしており、誤用していました。ひがさんから指摘を受け、気づきました、ありがとうございます。

ここから本文

以前書いた#appengine JavaのLow-Level API(低レベルAPI)入門というエントリで、com.google.appengine.api.datastore.Queryクラスの「親Keyのみ指定するコンストラクタ」について以下のように記述した。

コンストラクタに親キーのみ指定するものもあるんですが、それを使って何かが取得できた記憶が無いので使い方がよくわかってません。コレの使いどころがわかっている方、教えて下さると嬉しいです。

で、最近JUnitのテストケースをデプロイ環境で実行するServletを作っていて、そこで以前から作っているAPIの動作確認用のテストケースを偶然実行して気づいたのですが、親Keyを引数にするコンストラクタで作成したQueryは、想像通り(期待する通り)の動作をする、という事です。ローカルでは動作しませんが、デプロイした環境では動作します。

例えば、以下のような状態の時。

  • Kind1...kind1a, kind1b
  • Kind2...kind2a(kind1aの子),kind2b(kind1bの子),kind2c(kind1bの子)
  • kind3...kind3a(kind2a)の子,kind3b(kind2bの子)

上記の状態で、new Query(kind1a.getKey())すると、kind1a, kind2a, kind3a、が返されます。つまり、new Query("kind1", kind1a.getKey()), new Query("kind2", kind1a.getKey()), new Query("kind3", kind1a.getKey())をマージしたのと同じ結果です。つまり全てのKindを対象にしてEntityGroupがひとつ丸ごと取得できます。便利です。

Kindを指定しないならインデックスはどうやって定義するの?と思いますが、このクエリにはインデックスの定義が必要ありません。たぶんKindIndexテーブルのキーのprefix scanのみで動作しているんでしょうね。KindIndexテーブルのキーのprefix scanのみで動作するって事は…そぅ、sortもfilterもできません。ちなみに先の例で行くと、KindIndexテーブルのキーのprefix scanに使用されるIndexは次のようになっています。

  • kind1a
  • kind1a/kind2a
  • kind1a/kind2a/kind3a
  • kind1b
  • kind1b/kind2b
  • kind1b/kind2b/kind3b
  • kind1b/kind2c

というワケで、KindIndexテーブルのキーのprefix scanだけを使ってEntityGroupが簡単にごそっと取れる「べき」なのに、今まではローカルだけで試していて動作しない→「なんで?」となっていました。ローカルで動作しない場合も、デプロイ環境でも念のためチェックしとかなきゃダメですねぇ。

コメントを投稿