summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorHunternif <hunternif@gmail.com>2021-09-02 04:11:09 +0100
committerHunternif <hunternif@gmail.com>2021-09-02 04:11:09 +0100
commit05a1221591b287e482d0c63d89b04b57d18d4228 (patch)
tree9774444af3fbccced7f7276b3291d525509be33f /server
parent6ddc41347bae13a05005a7b8511257d92d04d8c1 (diff)
server: search term similar posts applies sort automatically
Diffstat (limited to 'server')
-rw-r--r--server/szurubooru/search/configs/post_search_config.py37
-rw-r--r--server/szurubooru/tests/search/configs/test_post_search_config.py27
2 files changed, 50 insertions, 14 deletions
diff --git a/server/szurubooru/search/configs/post_search_config.py b/server/szurubooru/search/configs/post_search_config.py
index c8eed18..4b2c8bb 100644
--- a/server/szurubooru/search/configs/post_search_config.py
+++ b/server/szurubooru/search/configs/post_search_config.py
@@ -122,29 +122,40 @@ def _pool_filter(
)(query, criterion, negated)
-# includes the given post itself
+# includes the given post itself, also applies sort
def _similar_filter(
query: SaQuery, criterion: Optional[criteria.BaseCriterion], negated: bool
) -> SaQuery:
assert criterion
- # subquery for tags of the given post (post id in criterion)
filter_func_tag = search_util.create_num_filter(model.PostTag.post_id)
+ pt_alias = sa.orm.aliased(model.PostTag)
+
+ # subquery for tags of the given post (post id in criterion)
tag_query = db.session.query(model.PostTag.tag_id)
tag_query = filter_func_tag(tag_query, criterion, False)
tag_query = tag_query.subquery("source_tags")
- # subquery for posts with matching tags
- pt_alias = sa.orm.aliased(model.PostTag)
- subquery = (
- db.session.query(pt_alias.post_id)
- .filter(pt_alias.tag_id.in_(tag_query))
- .group_by(pt_alias.post_id)
- .subquery("similar_posts")
- )
- expr = model.Post.post_id.in_(subquery)
if negated:
- expr = ~expr
- return query.filter(expr)
+ # negated query runs normally, doesn't apply sort
+ subquery = (
+ db.session.query(pt_alias.post_id)
+ .filter(pt_alias.tag_id.in_(tag_query))
+ .group_by(pt_alias.post_id)
+ .subquery("similar_posts")
+ )
+ expr = model.Post.post_id.in_(subquery)
+ return query.filter(~expr)
+ else:
+ # direct query applies sort
+ subquery = query.subquery("main_query")
+ return (
+ db.session.query(model.Post)
+ .join(pt_alias, pt_alias.post_id == model.Post.post_id)
+ .filter(pt_alias.tag_id.in_(tag_query))
+ .group_by(model.Post.post_id)
+ .join(subquery, pt_alias.post_id == subquery.c.id)
+ .order_by(sa.func.count(pt_alias.tag_id).desc())
+ )
def _create_metric_num_filter(name: str):
diff --git a/server/szurubooru/tests/search/configs/test_post_search_config.py b/server/szurubooru/tests/search/configs/test_post_search_config.py
index 3a347de..c9f2408 100644
--- a/server/szurubooru/tests/search/configs/test_post_search_config.py
+++ b/server/szurubooru/tests/search/configs/test_post_search_config.py
@@ -971,7 +971,7 @@ def test_around_query(
("similar:1", [6, 4, 1]),
("similar:2", [6, 5, 4, 2]),
("similar:3", [6, 5, 3]),
- ("similar:4", [6, 5, 4, 2, 1]),
+ ("similar:4", [6, 4, 5, 2, 1]),
("similar:5", [6, 5, 4, 3, 2]),
("similar:6", [6, 5, 4, 3, 2, 1]),
("-similar:1", [5, 3, 2]),
@@ -980,6 +980,9 @@ def test_around_query(
("-similar:4", [3]),
("-similar:5", [1]),
("-similar:6", []),
+ ("similar:4 sort:id,asc", [4, 6, 1, 2, 5]),
+ ("similar:4 b", [6, 4, 5, 2]),
+ ("similar:4 c", [6, 5]),
])
def test_filter_by_similar(
post_factory, tag_factory, verify_unpaged, input, expected_post_ids
@@ -998,3 +1001,25 @@ def test_filter_by_similar(
)
db.session.flush()
verify_unpaged(input, expected_post_ids, True)
+
+
+
+@pytest.mark.parametrize("input,expected_post_ids", [
+ ("similar:1", [3, 1, 2]),
+ ("similar:2", [3, 2, 1]),
+ ("similar:3", [3, 1, 2]),
+])
+def test_sort_by_similar(
+ post_factory, tag_factory, verify_unpaged, input, expected_post_ids
+):
+ tagA = tag_factory(names=["a"])
+ tagB = tag_factory(names=["b"])
+ tagC = tag_factory(names=["c"])
+ postAB = post_factory(id=1, tags=[tagA, tagB])
+ postA = post_factory(id=2, tags=[tagA])
+ postABC = post_factory(id=3, tags=[tagA, tagB, tagC])
+ db.session.add_all(
+ [tagA, tagB, tagC, postA,postAB, postABC]
+ )
+ db.session.flush()
+ verify_unpaged(input, expected_post_ids, True)