我有一个定义一些配置的字典,在这里我不会事先知道用户要构建的确切过滤器
它是这样指定的:
{"col1": ["val1", "~val2"],
"col2": ["val3", "val4"],
"col3": ["val5", "val6", "~val7", "~val8"]}
应翻译为:
WHERE (
col1 LIKE val1
AND
col1 NOT LIKE val2
)
OR (
col2 LIKE val3
OR
col2 LIKE val4
)
OR
(
(
col3 LIKE val5
OR
col3 LIKE val6
)
AND
col3 NOT LIKE val7
AND
col3 NOT LIKE val8
)
顶层条件始终是“或”(您匹配指定的一列或匹配指定的另一列)从不“与”
但是,在列表中,您可以匹配任何肯定的条件,但不能匹配任何否定的条件(这里的条件是字符串)
到目前为止,我尝试动态构建它的尝试看起来像这样:
def make_filter(definition):
f = {}
for variable in definition:
v = getattr(Target, variable)
f[v] = []
for col in definition[variable]:
f[v].append(col)
return f
def make_query(def_dict):
q = destination.query(Target)
filter = make_filter(def_dict)
for col in filter:
for val in filter[col]:
if '~' in val:
q = q.filter(sa.not_(col.like(val)))
else:
q = q.filter(col.like(val))
for record in q.all():
# do stuff
但是很明显,这通过'and'组合了所有条件-对于未知数量的条件,我看不到一种与'or'动态组合的方法...
只要可以明确指定同一组标准,那么这是解决此问题的更好方法,那么我可以修改规范。我并没有特别要求用户将所有肯定的标准放在所有否定的标准之前,但这是合理的。
答案 0 :(得分:0)
不确定上面给出的链接答案是否应该将其标记为重复-可能有所不同以至仍然有用,因此以防万一我基于链接答案发布我的解决方案以提高完整性:
def make_filter(definition):
f = {}
for variable in definition:
v = getattr(Target, variable)
f[v] = {"like": [], "not": []}
for col in definition[variable]:
if "~" in col:
f[v]["not"].append(re.sub('~', '', col))
else:
f[v]["like"].append(col)
return f
def make_query(def_dict):
q = destination.query(Target)
filter = make_filter(def_dict)
for item in filter:
like_this = filter[item]["like"]
not_this = filter[item]["not"]
if len(not_this):
for nt in not_this:
q = q.filter(sa.not_(item.like(nt)))
clauses = []
for lt in like_this:
clauses.append(item.like(lt))
q = q.filter(sa.or_(*clauses))
for record in q.all():
# do stuff