Merge 57915c6222
into 61b9f81e39
This commit is contained in:
commit
6bf88990fa
4 changed files with 209 additions and 0 deletions
|
@ -50,6 +50,22 @@
|
|||
<td><code>post-count</code></td>
|
||||
<td>alias of <code>usages</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>suggests</code></td>
|
||||
<td>with given suggested tags (accepts wildcards)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>implies</code></td>
|
||||
<td>with given implied tags (accepts wildcards)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>suggested-by</code></td>
|
||||
<td>suggested by given tags (accepts wildcards)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>implied-by</code></td>
|
||||
<td>implied by given tags (accepts wildcards)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>suggestion-count</code></td>
|
||||
<td>with given number of suggestions</td>
|
||||
|
|
|
@ -96,6 +96,50 @@ class TagSearchConfig(BaseSearchConfig):
|
|||
["implication-count"],
|
||||
search_util.create_num_filter(model.Tag.implication_count),
|
||||
),
|
||||
(
|
||||
["suggested-by"],
|
||||
search_util.create_nested_filter(
|
||||
model.Tag.tag_id,
|
||||
model.TagSuggestion.child_id,
|
||||
model.TagSuggestion.parent_id,
|
||||
model.TagName.tag_id,
|
||||
model.TagName.name,
|
||||
search_util.create_str_filter,
|
||||
),
|
||||
),
|
||||
(
|
||||
["suggests"],
|
||||
search_util.create_nested_filter(
|
||||
model.Tag.tag_id,
|
||||
model.TagSuggestion.parent_id,
|
||||
model.TagSuggestion.child_id,
|
||||
model.TagName.tag_id,
|
||||
model.TagName.name,
|
||||
search_util.create_str_filter,
|
||||
),
|
||||
),
|
||||
(
|
||||
["implied-by"],
|
||||
search_util.create_nested_filter(
|
||||
model.Tag.tag_id,
|
||||
model.TagImplication.child_id,
|
||||
model.TagImplication.parent_id,
|
||||
model.TagName.tag_id,
|
||||
model.TagName.name,
|
||||
search_util.create_str_filter,
|
||||
),
|
||||
),
|
||||
(
|
||||
["implies"],
|
||||
search_util.create_nested_filter(
|
||||
model.Tag.tag_id,
|
||||
model.TagImplication.parent_id,
|
||||
model.TagImplication.child_id,
|
||||
model.TagName.tag_id,
|
||||
model.TagName.name,
|
||||
search_util.create_str_filter,
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -226,3 +226,38 @@ def create_subquery_filter(
|
|||
return query.filter(expression)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def create_nested_filter(
|
||||
left_id_column: SaColumn,
|
||||
right_id_column: SaColumn,
|
||||
filter_column: SaColumn,
|
||||
nested_id_column: SaColumn,
|
||||
nested_filter_column: SaColumn,
|
||||
filter_factory: SaColumn,
|
||||
subquery_decorator: Callable[[SaQuery], None] = None,
|
||||
) -> Filter:
|
||||
filter_func = filter_factory(nested_filter_column)
|
||||
|
||||
def wrapper(
|
||||
query: SaQuery,
|
||||
criterion: Optional[criteria.BaseCriterion],
|
||||
negated: bool,
|
||||
) -> SaQuery:
|
||||
assert criterion
|
||||
nested = db.session.query(nested_id_column.label("foreign_id"))
|
||||
nested = nested.options(sa.orm.lazyload("*"))
|
||||
nested = filter_func(nested, criterion, False)
|
||||
nested = nested.subquery("t")
|
||||
subquery = db.session.query(right_id_column.label("foreign_id"))
|
||||
if subquery_decorator:
|
||||
subquery = subquery_decorator(subquery)
|
||||
subquery = subquery.options(sa.orm.lazyload("*"))
|
||||
subquery = subquery.filter(filter_column.in_(nested))
|
||||
subquery = subquery.subquery("t")
|
||||
expression = left_id_column.in_(subquery)
|
||||
if negated:
|
||||
expression = ~expression
|
||||
return query.filter(expression)
|
||||
|
||||
return wrapper
|
||||
|
|
|
@ -370,6 +370,120 @@ def test_filter_by_implication_count(
|
|||
verify_unpaged(input, expected_tag_names)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input,expected_tag_names",
|
||||
[
|
||||
("suggests:sug1", ["t1", "t3"]),
|
||||
("suggests:sug2", ["t1"]),
|
||||
("suggests:sug3", ["t2"]),
|
||||
("suggests:t1", []),
|
||||
("-suggests:sug1", ["sug1", "sug2", "sug3", "t2"]),
|
||||
],
|
||||
)
|
||||
def test_filter_by_suggests_tags(
|
||||
verify_unpaged, tag_factory, input, expected_tag_names
|
||||
):
|
||||
sug1 = tag_factory(names=["sug1"])
|
||||
sug2 = tag_factory(names=["sug2"])
|
||||
sug3 = tag_factory(names=["sug3"])
|
||||
tag1 = tag_factory(names=["t1"])
|
||||
tag2 = tag_factory(names=["t2"])
|
||||
tag3 = tag_factory(names=["t3"])
|
||||
db.session.add_all([sug1, sug3, tag2, sug2, tag1, tag3])
|
||||
tag1.suggestions.append(sug1)
|
||||
tag1.suggestions.append(sug2)
|
||||
tag2.suggestions.append(sug3)
|
||||
tag3.suggestions.append(sug1)
|
||||
db.session.flush()
|
||||
verify_unpaged(input, expected_tag_names)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input,expected_tag_names",
|
||||
[
|
||||
("suggested-by:t1", ["sug1", "sug2"]),
|
||||
("suggested-by:t2", ["sug3"]),
|
||||
("suggested-by:t3", ["sug4", "t2"]),
|
||||
("-suggested-by:t3", ["sug1", "sug2", "sug3", "t1", "t3",]),
|
||||
],
|
||||
)
|
||||
def test_filter_by_suggests_by_tags(
|
||||
verify_unpaged, tag_factory, input, expected_tag_names
|
||||
):
|
||||
sug1 = tag_factory(names=["sug1"])
|
||||
sug2 = tag_factory(names=["sug2"])
|
||||
sug3 = tag_factory(names=["sug3"])
|
||||
sug4 = tag_factory(names=["sug4"])
|
||||
tag1 = tag_factory(names=["t1"])
|
||||
tag2 = tag_factory(names=["t2"])
|
||||
tag3 = tag_factory(names=["t3"])
|
||||
db.session.add_all([sug1, sug3, tag2, sug2, tag1, tag3, sug4])
|
||||
tag1.suggestions.append(sug1)
|
||||
tag1.suggestions.append(sug2)
|
||||
tag2.suggestions.append(sug3)
|
||||
tag3.suggestions.append(tag2)
|
||||
tag3.suggestions.append(sug4)
|
||||
db.session.flush()
|
||||
verify_unpaged(input, expected_tag_names)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input,expected_tag_names",
|
||||
[
|
||||
("implies:sug1", ["t1", "t3"]),
|
||||
("implies:sug2", ["t1"]),
|
||||
("implies:sug3", ["t2"]),
|
||||
("implies:t1", []),
|
||||
("-implies:sug1", ["sug1", "sug2", "sug3", "t2"]),
|
||||
],
|
||||
)
|
||||
def test_filter_by_implies_tags(
|
||||
verify_unpaged, tag_factory, input, expected_tag_names
|
||||
):
|
||||
sug1 = tag_factory(names=["sug1"])
|
||||
sug2 = tag_factory(names=["sug2"])
|
||||
sug3 = tag_factory(names=["sug3"])
|
||||
tag1 = tag_factory(names=["t1"])
|
||||
tag2 = tag_factory(names=["t2"])
|
||||
tag3 = tag_factory(names=["t3"])
|
||||
db.session.add_all([sug1, sug3, tag2, sug2, tag1, tag3])
|
||||
tag1.implications.append(sug1)
|
||||
tag1.implications.append(sug2)
|
||||
tag2.implications.append(sug3)
|
||||
tag3.implications.append(sug1)
|
||||
db.session.flush()
|
||||
verify_unpaged(input, expected_tag_names)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input,expected_tag_names",
|
||||
[
|
||||
("implied-by:t1", ["sug1", "sug2"]),
|
||||
("implied-by:t2", ["sug3"]),
|
||||
("implied-by:t3", ["sug4", "t2",]),
|
||||
("-implied-by:t3", ["sug1", "sug2", "sug3", "t1", "t3",]),
|
||||
],
|
||||
)
|
||||
def test_filter_by_implied_by_tags(
|
||||
verify_unpaged, tag_factory, input, expected_tag_names
|
||||
):
|
||||
sug1 = tag_factory(names=["sug1"])
|
||||
sug2 = tag_factory(names=["sug2"])
|
||||
sug3 = tag_factory(names=["sug3"])
|
||||
sug4 = tag_factory(names=["sug4"])
|
||||
tag1 = tag_factory(names=["t1"])
|
||||
tag2 = tag_factory(names=["t2"])
|
||||
tag3 = tag_factory(names=["t3"])
|
||||
db.session.add_all([sug1, sug3, tag2, sug2, tag1, tag3, sug4])
|
||||
tag1.implications.append(sug1)
|
||||
tag1.implications.append(sug2)
|
||||
tag2.implications.append(sug3)
|
||||
tag3.implications.append(tag2)
|
||||
tag3.implications.append(sug4)
|
||||
db.session.flush()
|
||||
verify_unpaged(input, expected_tag_names)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input,expected_tag_names",
|
||||
[
|
||||
|
|
Reference in a new issue