Я пытаюсь реализовать механизм фильтрации тегов, где элементы могут иметь произвольное количество тегов, связанных с ними, и я хочу иметь возможность находить элементы, которые имеют один или все запрошенные теги.
Моя схема выглядит примерно так:
class Item(db.Entity):
tags = orm.Set("ItemTag")
class ItemTag(db.Entity):
item = orm.Required(Item)
tag = orm.Required(str)
orm.composite_key(item, tag)
orm.composite_key(tag, item)
Я могу легко фильтровать существующие запросы по одному тегу:
def filter_query_tag(query, tag:str):
return orm.select(i for i in query for t in i.tags if t.key == tag)
и могу найти элементы с любым тегов легко:
def filter_query_any_tag(query, tags:typing.Union(set,list,tuple)):
return orm.select(i for i in query for t in i.tags if t.key in tags)
, но попытка создать запрос, который находит все тегов, выдает ошибку:
def filter_query_all_tags(query, tags:typing.Union(set,list,tuple)):
for tag in tags:
query = orm.select(i for i in query for t in i.tags if t.key == tag)
return query
приводит к :
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/core.py", line 5562, in select
return make_query(args, frame_depth=cut_traceback_depth+1)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/core.py", line 5558, in make_query
return Query(code_key, tree.code, globals, locals, cells, left_join)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/core.py", line 5717, in __init__
translator = translator_cls(tree_copy, None, code_key, filter_num, extractors, vars, vartypes.copy(), left_join=left_join)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/sqltranslation.py", line 222, in __init__
translator.init(tree, parent_translator, code_key, filter_num, extractors, vars, vartypes, left_join, optimize)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/sqltranslation.py", line 396, in init
tableref = translator.sqlquery.add_tableref(name_path, parent_tableref, attr)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/sqltranslation.py", line 1211, in add_tableref
assert name_path not in sqlquery.tablerefs
AssertionError
Вероятно, проблема в том, что возникают проблемы с отображением нескольких имен соединений в одну и ту же таблицу, что, возможно, является ошибкой в ponyorm. Тем не менее, я подозреваю, что, возможно, есть лучший способ построить запрос без необходимости выполнять несколько объединений и фильтров.
Я попытался использовать orm.left_join
вместо orm.select
, например:
def filter_query_all_tags(query, tags:typing.Union(set,list,tuple)):
for tag in tags:
query = orm.left_join(i for i in query for t in i.tags if t.key == tag)
return query
В этом случае я могу фильтровать по двум тегам одновременно, но если я добавлю третий тег, я получу:
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/core.py", line 5566, in left_join
return make_query(args, frame_depth=cut_traceback_depth+1, left_join=True)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/core.py", line 5558, in make_query
return Query(code_key, tree.code, globals, locals, cells, left_join)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/core.py", line 5717, in __init__
translator = translator_cls(tree_copy, None, code_key, filter_num, extractors, vars, vartypes.copy(), left_join=left_join)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/sqltranslation.py", line 222, in __init__
translator.init(tree, parent_translator, code_key, filter_num, extractors, vars, vartypes, left_join, optimize)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/sqltranslation.py", line 343, in init
names, try_extend_prev_query=not i)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/sqltranslation.py", line 598, in process_query_qual
subquery_ast = prev_translator.construct_subquery_ast(prev_limit, prev_offset, aliases=aliases)
File "/Users/fluffy/.local/share/virtualenvs/Publ-FUB3ZG92/lib/python3.7/site-packages/pony/orm/sqltranslation.py", line 625, in construct_subquery_ast
assert not star and len(aliases) == len(select_ast) - 1
AssertionError
Есть ли примитив или idiomati c выражение в пониоме, которое позволяет мне указать, что все значения набора должны присутствовать в ItemTag
значениях для любого данного Item
?