2010-10-18 12 views
6

Có cách nào thông minh để tránh thực hiện truy vấn tốn kém với mệnh đề IN trong các trường hợp như sau không?Giảm thiểu các truy vấn phụ bằng truy vấn IN trên AppEngine (trăn)

Tôi đang sử dụng Google App Engine để xây dựng ứng dụng Facebook và tại một thời điểm nào đó, tôi cần truy vấn kho dữ liệu để nhận tất cả các thực thể thuộc về bất kỳ người bạn facebook nào của người dùng đã cho.

Giả sử tôi có một vài tổ chức theo mô hình như vậy:

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

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

Tại một số điểm tôi truy vấn Facebook để có được danh sách bạn bè của người dùng nhất định và tôi cần phải thực hiện truy vấn sau đây

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

Nếu tôi làm như vậy, AppEngine sẽ thực hiện truy vấn con cho mỗi tôi d trong friend_ids, có thể vượt quá số truy vấn phụ tối đa mà bất kỳ truy vấn nào cũng có thể sinh ra (30).

Có cách nào tốt hơn để thực hiện việc này (ví dụ: giảm thiểu số truy vấn) không? Tôi hiểu rằng không có mối quan hệ và tham gia sử dụng kho dữ liệu nhưng, đặc biệt, tôi sẽ xem xét thêm các trường mới vào lớp User hoặc Thing nếu nó giúp làm cho mọi thứ dễ dàng hơn.

Trả lời

5

Tôi không nghĩ rằng có một giải pháp tao nhã, nhưng bạn có thể thử điều này:

Trên mô hình dùng, sử dụng Facebook ID như tên chủ chốt, và lưu trữ danh sách mỗi người dùng của sự vật trong một ListProperty.

class Thing(db.Model): 
    ... 

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

Entity tạo sẽ đi như thế này:

user = User.get_or_insert(my_facebook_id) 

thing = Thing() 
thing.put() 

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

Retrieval mất 2 truy vấn:

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 Một tùy chọn khác là đặt Mọi thứ con thành Người dùng cho phép truy vấn tổ tiên cho một loại điều cụ thể được trả lại. Việc sử dụng các key_names là rất quan trọng đối với điều này thực sự làm việc. – kevpie

+0

Thật tuyệt vời, tôi thậm chí còn làm Mọi thứ thành Người dùng theo gợi ý của kevpie. Tôi đã phải đối phó với một vài vấn đề hơn, mặc dù: a) Tôi không lưu trữ một thực thể người dùng cho mỗi friend_id, vì vậy tôi cần phải lọc các giá trị None tôi nhận được khi truy vấn bằng cách sử dụng get_by_key_name; b) Tôi cũng phải lọc mọi thứ bằng một số trường khác, nhưng tôi làm điều đó trên các thực thể tôi tìm nạp sau khi tôi lấy chúng từ DataStore. Có cách nào tốt hơn để làm điều đó không? – abahgat

+0

Hãy chắc chắn để xem các cuộc đàm phán Nick đăng trong câu trả lời của mình. Bạn có thể muốn sử dụng một thực thể chỉ mục kết hợp với một thuộc tính danh sách. Điều này được thể hiện trong cuộc trò chuyện đầu tiên được đăng bởi Nick. – kevpie

3

This Google I/O talk bởi Brett Slatkin đề cập đến tình hình chính xác mà bạn đang làm việc với. Xem thêm his follow up talk năm nay.

+0

Tôi e rằng bạn đã đăng hai lần cùng một liên kết đến bài nói chuyện cuối cùng. Bạn đang đề cập đến cái này? http://www.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html – abahgat

+0

Có, tôi đã tham gia. Xin lỗi, đã sửa. –