2010-10-18 13 views
6

Czy istnieje jakiś sprytny sposób na uniknięcie kosztownych zapytań z klauzulą ​​IN w takich przypadkach, jak ten następny?Zminimuj podzapytania za pomocą zapytań IN w AppEngine (python)

Korzystam z Google App Engine do budowy aplikacji na Facebooku iw pewnym momencie (oczywiście) muszę wysłać zapytanie do magazynu danych, aby uzyskać wszystkie podmioty należące do któregokolwiek z przyjaciół Facebooka danego użytkownika.

Załóżmy, że mam kilka podmiotów modelowane jako takie:

class Thing(db.Model): 
    owner = db.ReferenceProperty(reference_class=User, required=True) 
    owner_id = db.StringProperty(required=True) 
    ... 

i

class User(db.Model): 
    id = db.StringProperty(required=True) 
    ... 

W pewnym momencie kwerendy Facebook, aby uzyskać listę znajomych danego użytkownika i muszę wykonać następujące zapytanie

# get all Thing instances that belong to friends 
query = Thing.all() 
query.filter('owner_id IN', friend_ids) 

Gdybym to zrobił, AppEngine byłoby wykonać podzapytania dla każdego i d w friend_ids, prawdopodobnie przekraczając maksymalną liczbę podkwerend, może pojawić się zapytanie (30).

Czy istnieje lepszy sposób to zrobić (tj. Minimalizując liczbę zapytań)? Rozumiem, że nie ma żadnych powiązań i łączy przy użyciu datastore, ale w szczególności, rozważyłbym dodanie nowych pól do klasy User lub Thing, jeśli pomaga to w ułatwianiu.

Odpowiedz

5

nie sądzę istnieje eleganckie rozwiązanie, ale można spróbować to:

na modelu użytkownika, należy użyć Facebook ID jako nazwę klucza, i przechowywać listy każdego użytkownika rzeczy w ListProperty.

class Thing(db.Model): 
    ... 

class User(db.Model): 
    things = db.ListProperty(db.Key) 
    ... 

tworzenie Entity pójdzie tak:

user = User.get_or_insert(my_facebook_id) 

thing = Thing() 
thing.put() 

user.things.append(thing.key()) 
user.put() 

pobierania trwa 2 zapytania:

friends = User.get_by_key_name(friend_ids) 
thing_keys = [] 

for friend in friends: 
    thing_keys.extend(friend.things) 

things = db.get(thing_keys) 
+0

+1 Inną opcją jest sprawienie, aby obiekty potomne dla użytkownika zezwalały na zapytania przodków dotyczące określonego rodzaju rzeczy do zwrócenia. Użycie key_names ma kluczowe znaczenie dla tego naprawdę działającego. – kevpie

+0

To wspaniale, nawet uczyniłem Rzeczy dziećmi Użytkownikiem, jak sugeruje kevpie. Miałem jednak do czynienia z jeszcze kilkoma problemami: a) Nie przechowuję encji User dla każdego friend_id, więc muszę filtrować wartości None, które otrzymuję, gdy wysyłam zapytania za pomocą get_by_key_name; b) Muszę odfiltrować rzeczy także przez inne pola, ale robię to na elementach, które pobieram po ich pobraniu z DataStore. Czy istnieje lepszy sposób na zrobienie tego? – abahgat

+0

Pamiętaj, aby obejrzeć wypowiedzi Nicka zamieszczone w jego odpowiedzi. Możesz użyć indeksu połączonego z właściwością listy. Jest to pokazane w pierwszej rozmowie napisanej przez Nicka. – kevpie

3

This Google I/O talk Brett Slatkinem rozwiązuje dokładnej sytuacji masz do czynienia. Zobacz także his follow up talk w tym roku.

+0

Obawiam się, że opublikowałeś dwa razy ten sam link do ostatniej rozmowy. Czy odnosiłeś się do tego? http://www.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html – abahgat

+0

Tak, byłem. Przepraszamy, poprawiono. –

Powiązane problemy