2009-07-28 6 views
1

this different but not unrelated questionを参考に、サンプルモデルを借用します。db.Model ListPropertyの特定の数の項目を照合する最も効率的な方法

class Foo(db.Model): bars = db.ListProperty(db.Key) 

class Bar(db.Model): pass 

私は特定のFooエンティティを持っているし、私もそのバーで特定のバーキーListPropertyを含む他のfooエンティティのすべてを取得したい場合は、私は次のクエリを使用します。

related_foos = Foo.all().filter('bars', bar_entity).fetch(fetch_count) 

少なくともN個の一致するバーエンティティを持つモデル種類Fooの他のすべてのエンティティを検索する場合はどうなりますか? forループでこれを行う明白な方法は、大幅な非効率を伴い、モデル自体を実際に変更してこれを簡単にするのが最善の方法かもしれませんが、そうする方法は明白ではありません。

+0

答えは、エンティティの既知のリストとの照合を目的としている場合に役立ちますが、実際に質問している内容の例があります。 Fooのインスタンスを10個のバーキーbarsプロパティ。私は少なくとも2つの一致するバーキーを持つ他のすべてのFooエンティティを取得したい。 私がこの質問で言ったように、これは複数のデータストアの読み込みで行うことができますが、読み込みが1つだけで済むか、必要な読み込み回数が少なくて済むのは本当に素晴らしいことです。 – jamtoday

答えて

1

10個のbar_entitiesを持つfooレコードを検索し、これらの10個のエンティティのうち少なくとも2個を持つすべてのfooレコードを検索すると、45個の可能な等価値10!/(2!*(10-2)!)= 45が得られます。

これは、10_C_(2-1)= 10の読み込みで推測できます。 1回の読み取りにこれを削減するために

SELECT * from table WHERE bar="1" AND bar in ["2", "3", "4", "5", "6", "7", "8", "9", "0"] 
SELECT * from table WHERE bar="2" AND bar in ["3", "4", "5", "6", "7", "8", "9", "0"] 
SELECT * from table WHERE bar="3" AND bar in ["4", "5", "6", "7", "8", "9", "0"] 
etc. 

はfooのレコードが追加されたときに指定したレコードのすべての2つの組み合わせを持っていた別のテーブルを読み込むことが必要となります。

Say you had 

foo_table 
foo1 [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] 
foo2 [1, 3, 4] 
foo3 [1, 2, a] 
foo4 [b, 6, c] 

foo_combo_2_table 
Parent Combination 
foo1 12 
foo1 13 
... and all 45 foo1 combinations each in its own row 
foo2 13 
foo2 14 
foo2 34 
foo3 12 
foo3 1a 
foo3 2a 
etc. 

Now you can do a 

indexes = SELECT __KEY__ from foo_combo_2_table WHERE combination IN [12, 13, 14, 15, ... all 45] 
keys = [k.parent() for k in indexes] # you would need to filter for duplicates 

このようにして、インデックスの問題が爆発することはありません。

これらのそれぞれに対して3つまたは4つのエンティティを実行する場合は、foo_combo_n_tableを作成するか、10_C_(n-1)回の読み取りを行う必要があります。

2

あなたは、単に繰り返し同じフィルタを適用することができます。

related_foos = Foo.all().filter('bars', bar_entity).filter('bars', bar_entity_2).fetch(fetch_count) 

あるいは、データ駆動型:

q = Foo.all() 
for bar in bar_entities: 
    q.filter('bars', bar) 
related_foos = q.fetch(fetch_count) 

クエリに任意の不平等やソート順を適用しない場合は、データストアを適用するフィルターの数に関係なく、組み込み索引およびマージ結合戦略を使用して照会を実行することができます。しかし、不等式や並べ替え順序が必要な場合は、フィルタリングしたい棒の数ごとにインデックスを持たなければならないため、インデックスが爆発的になります(避けるのが最善です)。

+0

これは良い答えです...しかし、私の質問には答えません。私は質問へのコメントで精緻化した。 – jamtoday

+0

「少なくとも2つの一致するバーキーを持つ他のすべてのFooエンティティを取得したいです。 - 何をマッチング?あなたはキーのリストを持っていますか?2つのセットの共通部分に少なくとも2つのアイテムが含まれているすべてのエンティティを検索したいですか? –

関連する問題