2009-07-28 13 views
1

zu vergleichen In Bezug auf this different but not unrelated question werde ich die Beispielmodelle ausleihen.Der effizienteste Weg, um eine bestimmte Anzahl von Elementen in einer db.Model ListProperty

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

class Bar(db.Model): pass 

Wenn ich eine bestimmte Foo Einheit haben und ich möchte alle anderen foo Einheiten auch eine bestimmte Bar Key in seinen Bars Listproperty enthält, erhalten, würde ich die folgende Abfrage verwenden:

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

Wie wäre es, wenn ich alle anderen Entitäten der Modellart Foo finden möchte, die mindestens N übereinstimmende Balkeneinheiten haben? Der offensichtliche Weg, dies mit einer For-Schleife zu tun, würde drastische Ineffizienzen beinhalten, und es wäre vielleicht am besten, das Modell selbst zu ändern, um dies zu vereinfachen, aber es scheint nicht offensichtlich zu sein, wie dies zu erreichen ist.

+0

Die Antworten sind hilfreich, wenn das Ziel mit einer bekannten Liste von Entitäten übereinstimmt, aber hier ist ein besseres Beispiel für meine Frage: Nehmen wir an, ich habe eine Instanz von Foo mit 10 bar-Tasten aufgelistet die Bars Eigenschaft. Ich möchte alle anderen Foo-Entitäten mit mindestens 2 übereinstimmenden Bar-Schlüsseln erhalten. Wie ich in der Frage sagte, könnte dies mit mehreren Datenspeicher Lesevorgänge getan werden, aber es wäre wirklich toll, wenn es mit nur einem Lesevorgang oder der geringsten Anzahl von Lesevorgängen getan werden könnte. – jamtoday

Antwort

1

Gegeben ein foo record mit 10 bar_entities und der Suche nach allen foo-Records, die mindestens 2 dieser 10 Entitäten enthalten, würde 45 mögliche Gleichheitswerte ergeben 10!/(2! * (10-2)!) = 45.

Dies kann in 10_C_ (2-1) = 10 liest abgeleitet werden.

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. 

diese Lese auf einen reduzieren würde, dass, sobald ein foo Datensatz Sie eine separate Tabelle bevölkern wird hinzugefügt, die für einen bestimmten Datensatz alle zwei Kombinationen hatten.

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 

Auf diese Weise werden Sie keine explodierenden Indexprobleme bekommen.

Wenn Sie auch 3 oder 4 Entitäten als jede dieser Entitäten erstellen möchten, müssen Sie eine foo_combo_n_table erstellen oder eine 10_C_ (n-1) Anzahl von Lesevorgängen erstellen.

2

Sie können einfach den gleichen Filter anwenden wiederholt:

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

Oder datengetriebener:

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

Wenn Sie gelten keine Ungleichheiten oder Aufträge sortieren, um die Abfrage, um den Datenspeicher kann die Abfragen mithilfe der integrierten Indizes und der Merge-Join-Strategie ausführen, unabhängig davon, wie viele Filter Sie anwenden. Wenn Sie jedoch eine Ungleichheit oder Sortierreihenfolge benötigen, benötigen Sie einen Index für jede Anzahl von Balken, auf die Sie filtern möchten. Dies führt zu explodierenden Indizes (und vermeiden Sie dies am besten!)

+0

Das ist eine gute Antwort ... aber beantwortet meine Frage nicht. Ich habe in einem Kommentar auf die Frage ausgearbeitet. – jamtoday

+0

Sie sagen "Ich möchte alle anderen Foo-Entitäten mit mindestens 2 übereinstimmenden Bar-Tasten erhalten." - was passt? Haben Sie eine Liste von Schlüsseln und möchten Sie alle Entitäten finden, in denen die Schnittmenge der beiden Sätze mindestens zwei Elemente enthält? –

Verwandte Themen