如何根据条件动态构建查询?
How to build a query dynamically, based on conditions?
我想根据用户请求,根据可能条件的范围 (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 == *)更优化。
我知道您可以链接过滤器,但由于查询对象是不可变的,所以不确定这是否对我有帮助。
是的,这是可能的。来自 Filtering by Property Values:
Instead of specifying an entire query filter in a single expression,
you may find it more convenient to build it up in steps: for example:
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
is equivalent to the query
variable from the previous
example. Note that query objects are immutable, so the construction of
query2
does not affect query1
and the construction of query3
does not affect query1
or query2
.
您可以使用这种增量查询构建技术根据需要有条件地添加过滤器。例如(这假定可选条件之间的总体 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通过应用相应的查询对象获得的查询对象筛选。由关联的日志消息确认。
有一种更优雅的方法可以做到这一点。顺便说一句,动态性更强:
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
我想根据用户请求,根据可能条件的范围 (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 == *)更优化。
我知道您可以链接过滤器,但由于查询对象是不可变的,所以不确定这是否对我有帮助。
是的,这是可能的。来自 Filtering by Property Values:
Instead of specifying an entire query filter in a single expression, you may find it more convenient to build it up in steps: for example:
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
is equivalent to thequery
variable from the previous example. Note that query objects are immutable, so the construction ofquery2
does not affectquery1
and the construction ofquery3
does not affectquery1
orquery2
.
您可以使用这种增量查询构建技术根据需要有条件地添加过滤器。例如(这假定可选条件之间的总体 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通过应用相应的查询对象获得的查询对象筛选。由关联的日志消息确认。
有一种更优雅的方法可以做到这一点。顺便说一句,动态性更强:
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