データストアのクエリ
非等号とINフィルタ
非等号とは「!=」のこと。INフィルタとはたとえば
Property IN(1, 2, 3)
と書くと、Propertyという名のプロパティの値が1か2か3のエンティティをかき集めてくれるフィルタです。
実はこれら2つのフィルタは別のフィルタに置き換えられて処理されます。
置き換え前 | 置き換え後 |
---|---|
A != 1 | A < 1とA > 1 |
B IN (1, 2, 3) | B = 1 OR B = 2 OR B = 3 |
特にINフィルタはANDでつなげるとものすごい数のフィルタに置き換えられてしまいます。たとえば
C IN (1, 2, 3) AND D IN (4, 5, 6)
というフィルタは
(C = 1 AND D = 4) OR (C = 1 AND D = 5) OR ...
という全組み合わせをORでつなげたフィルタになります。この位ならまだいいですが、INフィルタをたくさんつなげてしまうと、その組み合わせ数分のフィルタでクエリを実行してしまうことになります。
Unsetされたプロパティと、インデックスを持たないプロパティ
Unset、つまりあるプロパティの値を持たないエンティティについて。RDBと違い、データストアは種別で定義されているプロパティの値を持つことは必須ではありません。以前紹介したアプリでは種別は以下のように定義していました。
class Player(db.Model): name = db.StringProperty() level = db.IntegerProperty() score = db.IntegerProperty() charclass = db.StringProperty() create_date = db.DateTimeProperty(auto_now_add=True)
たとえばscoreプロパティの値を設定しないままデータストアに保存することも可能なのです。ここはリレーショナルデータベースとの違いがよく分かるポイントです。
name = self.request.get('name') level = self.request.get('level') charclass = self.request.get('class') player = Player( name = name, level = int(level), charclass = charclass) player.put()
次にインデックスを持たないプロパティについて・・・ですが、プロパティがインデックスを持たないってどういうこと?と思ったんですが、よく考えるとそんなに難しくありません。
データストアAPIはインデックスがないと何も出来ません (エンティティを取得することが出来ない) 。その代わり保存にかかる時間が短縮されます。意味のない (nullとかNoneとか) って値をいちいち入れるくらいだったら始めから入れない方がよいかな、とも思います。
でも直感的じゃないですね。リレーショナルデータベースに慣れてしまっているからでしょうかね。