🧨
Datastoreで虚無値を扱う際のトラップ
Firestore Datastoreモードで虚無値を扱う際にはトラップが存在するのでまとめます。
クエリで指定されたプロパティがないエンティティは無視される
Datastoreでは、プロパティが存在しない、ということをMySQLでいう IS NULL
のようにクエリすることはできません。
ここに書かれている通りではありますが、エンティティがA
というキーを持たない場合は、そのエンティティはA
キーのインデックスに乗らず、いかなる手段を用いてもA
キーでのクエリ結果には乗りません。
将来的にA
に虚無値を持つエンティティをクエリしたい可能性がある場合にはA
に明示的にnull
を指定しておきます。
null
を持つエンティティが想定外のクエリの結果に入る
const query = datastore.createQuery("Foo").filter("Prop", "<", 0);
const [entities] = await datastore.runQuery(query);
上記のような実装で、Propがnullのエンティティが返ります。
どうやら、nullという値は全ての数値よりも小さい値としてインデックスされるようで、 filter("Prop", "<", -9223372036854775295)
としてもnullは入ってきます。
これを回避するには、以下のように実装します。
const query = datastore.createQuery("Foo").filter("Prop", "<", 0).filter("Prop", ">", null);
Goではnullをクエリできない?
ドキュメントや実装を読む限りでは、Goのdatastoreライブラリではnullをクエリするための実装が用意されていません。
var entities []Entity
q := datastore.NewQuery("Foo").Filter("Prop =", nil)
if _, err := client.GetAll(ctx, q, &entities); err != nil {
log.Fatal(err)
}
上記のような実装でnullをクエリできそうな気がするのですが、 panic: reflect: call of reflect.Value.Interface on zero Value
とFatalを吐きます。
もしクエリする方法をご存知の方がいらっしゃいましたら教えてください。
擬似的には、 q := datastore.NewQuery("Foo").Filter("Prop <", -9223372036854775808)
とすることでクエリできますが、うーん・・・。
Discussion