У меня есть словарь, который определяет некоторую конфигурацию, где я не буду знать заранее точные фильтры, которые мой пользователь хочет построить
указано так:
{"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
но очевидно, что это объединяет все критерии с помощью 'и' - я не вижу способа динамически комбинировать с 'или' для неизвестного числа условий ...
Я могу изменить спецификации, если это лучший способ решить эту проблему, при условии, что один и тот же набор критериев может быть задан однозначно. Я специально не требовал от пользователей ставить все положительные критерии перед всеми отрицательными, но это разумно, например.