我有一个定义了一些配置的字典,我不会提前知道我的用户想要构建的确切过滤器
它是这样指定的:
{"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
但显然,这通过“和”组合了所有条件 - 我看不到一种在未知数量的条件下动态与“或”组合的方法......
只要可以明确指定同一组标准,如果这是解决此问题的更好方法,我可以修改规范。我没有特别要求用户将所有积极标准放在所有消极标准之前,但这是合理的。
最佳答案
考虑到上面提供的链接答案,不确定这是否应该被标记为欺骗 - 可能足够不同,仍然有帮助,所以以防万一我根据链接答案发布我的解决方案以确保完整性:
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
关于python - 在 sqlalchemy 中动态生成过滤器,混合使用 and/or 和 not/like,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53095303/