2017-07-01 81 views
0

我正在爲一個項目使用GAE python(webapp2)框架並且有一個與ndb查詢相關的問題。讓我舉個例子來解釋清楚:Google App Engine - 我如何對ndb查詢返回的結果執行python ndb查詢?

這裏是一個NDB模式,我有:

class Example(ndb.Model): 
    userid = ndb.StringProperty() 
    field1 = ndb.StringProperty() 
    field2 = ndb.StringProperty() 

這裏是我一直在使用上述模型建立的實體:

[Example(key=Key('Example', '1~A~B'), field1=u'B', field2=u'A', userid=u'1'), 
Example(key=Key('Example', '1~C~D'), field1=u'D', field2=u'C', userid=u'1'), 
Example(key=Key('Example', '2~A~B'), field1=u'B', field2=u'A', userid=u'2'), 
Example(key=Key('Example', '2~C~D'), field1=u'D', field2=u'C', userid=u'2'), 
Example(key=Key('Example', '3~A~B'), field1=u'B', field2=u'A', userid=u'3'), 
Example(key=Key('Example', '3~X~Y'), field1=u'Y', field2=u'X', userid=u'3'), 
Example(key=Key('Example', '4~C~D'), field1=u'D', field2=u'C', userid=u'4'), 
Example(key=Key('Example', '4~E~F'), field1=u'F', field2=u'E', userid=u'4'), 
Example(key=Key('Example', '5~A~B'), field1=u'B', field2=u'A', userid=u'5'), 
Example(key=Key('Example', '5~X~Y'), field1=u'Y', field2=u'X', userid=u'5') 
] 

鑑於以上數據我想找到以下內容: - 查找所有滿足以下兩個條件的用戶ID:

field1='B', field2='A' 
and field1='D', field2='C' 

在上面的例子以下用戶id將符合該條件:

userid='1' 
userid='2' 

所以我的問題是,我們有可能使用單一NDB查詢發現上面的結果呢?如果是這樣如何?

我知道現在做到這一點的方法只能用OR NDB查詢來實現,我們找到匹配

Example.query(ndb.OR(ndb.AND(field1='B' AND field2='a'), ndb.AND(field1='D' AND field2='C'))) 

然後遍歷這些結果(在python),然後有一個邏輯的所有記錄僅提取具有 FIELD1 =「B」,FIELD2 =「A」 和FIELD1 =「d」,FIELD2 =「C」的那些用戶ID

這似乎並不是一種有效的方法,因爲以下原因: - 我們不必要地用OR組合提取超過需要的記錄。 - 如果我們使用fetch_page限制結果,則無法知道將使用我們的標準篩選出多少條記錄。根據我們的限制,甚至可能會導致空記錄。

或者如果有一種方法可以首先找到field1 ='B'和field2 ='A'的所有用戶ID,然後在此結果中直接查詢以找到所有userid,其中field1 ='D'和field2 =' C',這也將解決問題。所以這是查詢查詢結果。

欣賞您的輸入/建議。謝謝。

回答

1

是的,ndb.OR操作效率不高,可能導致組合爆炸,請參閱Combining AND and OR Operations中的討論。

還請記住,您正在查詢Example元素,而不是用戶ID。這意味着在field1='B' and field2='A'查詢的結果內您無法真正查詢field1='D' and field2='C' - 結果將始終爲空,因爲field1不能同時爲'D''B'

所以,你真的需要做兩個單獨的查詢,提取每個結果中的userids集合,然後檢查兩個集合的交集。可以使用distinct projection queries(實驗!),以更有效地獲取用戶列表:

query_1 = Example.query(ndb.AND(Example.field1='B' AND Example.field2='A'), 
         projection=[Example.userid], distinct=True)) 
query_2 = Example.query(ndb.AND(Example.field1='D' AND Example.field2='C'), 
         projection=[Example.userid], distinct=True)) 

users_1 = set([example.userid for example in query_1.fetch()]) 
users_2 = set([example.userid for example in query_2.fetch()]) 

users_list = list(users_1 & users_2) 

注:我並沒有想上面的代碼,它是僅基於文檔。