読者です 読者をやめる 読者になる 読者になる

DataStore で Only ancestor queries are allowed inside transactions. のエラー

GCP


DataStore で以下のエラーが出た。

Only ancestor queries are allowed inside transactions. のエラー

ググると以下がヒット。
http://stackoverflow.com/questions/14397207/why-do-i-get-only-ancestor-queries-are-allowed-inside-transactions-error

結論としては、
トランザクション内でエンティティを取得するには AncestorQuery or Get() or GetMult() しか利用できない。

つまり、
DataStore が StrongConsistency を担保するのは
AncestorQuery or Get() or GetMult() のみである。

なので、
例えば、
同一kind内でkey以外のユニークなプロパティを持とうとする場合に、
トランザクション内でユニークなことを保証することはできない。

具体的な例で言うと、
User kind があって、keyが int64 で自動採番である場合に、
User kind に name をユニークで保持することはできない。
できないことはないが、実現方法が限られる。

ユニークで保持することができるケースは以下。

1.name を key にする
2.User kind を Ancestor で取得できるような親のkindが存在する
3.別kindでユニークを担保する


1.name を key にする
 name をそのまま key として扱うのに抵抗がある場合は、ハッシュ化したものを key にしてもいい。
 ただ、name を key にするというのは、
 「keyが int64 で自動採番である」という前提条件上、不可能なので、
 「User kind のkeyをnameにする」というように、
 データ構造自体を変更する必要がある。

2.User kind を Ancestor で取得できるような親のkindが存在する
 User kind を Ancestor で取得する場合でも、
 親のkind別でユニークが担保されるだけなので、
 kind 全体でユニークを担保することはできない。
 そもそも、親のkindが存在しなければAncestorQueryは利用できないので、事前に考える必要がある。


3.別kindでユニークを担保する
 「keyが int64 で自動採番である」という前提条件で
 name が kind 全体でユニークだることを担保したい場合は、
 name を key にした別のkindを用意して、
 その kind でユニークを担保する必要がある。
 http://stackoverflow.com/questions/11335651/how-to-handle-an-entity-with-two-unique-properties


ということで、
DataStoreではユニークな値をキーにするのが基本になるし、
トランザクション内でエンティティを取得するには
AncestorQuery or Get() or GetMult() しか利用できない
というお話でした。