1

この異なるが無関係ではない質問を参照して、サンプルモデルを借ります。

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

class Bar(db.Model): pass

特定の Foo エンティティがあり、バーの ListProperty に特定のバー Key を含む他のすべての foo エンティティを取得したい場合は、次のクエリを使用します。

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

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

4

2 に答える 2

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)

不等式や並べ替え順序をクエリに適用しない場合、データストアは、適用するフィルタの数に関係なく、組み込みのインデックスとマージ結合戦略を使用してクエリを実行できます。ただし、不等式または並べ替え順序が必要な場合は、フィルタリングする可能性のあるバーの数ごとにインデックスを用意する必要があります。これは、インデックスの爆発につながります (したがって、避けるのが最善です!)

于 2009-07-29T22:03:55.980 に答える
1

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

これは、10_C_(2-1)=10 回の読み取りで推測できます。

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.

これを 1 回の読み取りに減らすには、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) 回の読み取りを実行する必要があります。

于 2009-08-03T04:26:12.863 に答える