如何根据条件动态构建查询?

时间:2017-01-09 18:37:45

标签: python google-app-engine app-engine-ndb

我想根据用户请求在可能的标准范围(0-4)上查询数据存储区。 NDB中的查询构建如下:

query = Account.query(Account.userid >= 40, Account.userid < 50)

我有什么方法可以做类似的事情:

myfilter = []
myfilter.push('Account.userid >= 40')
myfilter.push('Account.userid < 50')
myfilter.push('Account.name == "John"')
query = Account.query(*myfilter)

根据条件,可能有0到4个过滤器参数。我的假设(这可能是错误的)是省略过滤器比使用全能(例如,Account.userid == *)更为优化,如果不需要它。

我知道你可以链接过滤器,但由于查询对象是不可变的,所以不确定这对我有帮助。

2 个答案:

答案 0 :(得分:2)

这样做有一种更优雅的方式。顺便说一下,更有活力:

def build_query_by(ndb_class, filters, sorts):
    """
    ndb_class: the ndb model class to query
    filters: a list of tuples of properties, operations and values
    sorts: a list of tuples of properties and order symbol
    """
    q = ndb_class.query()
    for prop, operation, value in filters:
        if operation == '==':
            q = q.filter(getattr(ndb_class, prop) == value)
        elif operation == '>=':
            q = q.filter(getattr(ndb_class, prop) >= value)
        elif operation == '<=':
            q = q.filter(getattr(ndb_class, prop) <= value)
        # more operations...

    for prop, symbol in sorts:
        if symbol == '-':
            q = q.order(-getattr(ndb_class, prop))
        else:
            q = q.order(getattr(ndb_class, prop))
    return q

答案 1 :(得分:1)

是的,有可能。来自Filtering by Property Values

  

而不是在单个表达式中指定整个查询过滤器,   您可能会发现按步骤构建它更方便:例如:

query1 = Account.query()  # Retrieve all Account entitites
query2 = query1.filter(Account.userid >= 40)  # Filter on userid >= 40
query3 = query2.filter(Account.userid < 50)  # Filter on userid < 50 too
     

query3相当于之前的query变量   例。注意查询对象是不可变的,所以构造   query2不会影响query1query3的构建   不会影响query1query2

您可以使用此类增量查询构建技术根据需要有条件地添加过滤器。例如(假设可选条件之间的整体AND):

query = Account.query()  # Retrieve all Account entitites
loggin.error(query)

if filter_by_userid:
    query = query.filter(Account.userid >= 40, Account.userid < 50)
    loggin.error(query)

if filter_by_username:
    query = query.filter(Account.name == "John")
    loggin.error(query)

loggin.error('Final: %s' % query)

上面的代码片段明确地利用了查询对象的不可变性,每个对query变量的赋值实际存储了通过应用相应过滤器获得的 new 查询对象。由关联的日志消息确认。