2017-07-01 107 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) 

注:我并没有想上面的代码,它是仅基于文档。