From fe45ea83c054f7ce9301cfb7ffb43987b6ac59b5 Mon Sep 17 00:00:00 2001 From: drew2a Date: Wed, 2 Feb 2022 17:38:40 +0700 Subject: [PATCH] Change tag search condition from `or` to `and` --- .../tests/test_remote_search_by_tags.py | 4 +-- .../tribler_core/components/tag/db/tag_db.py | 22 +++++++++++--- .../components/tag/db/tests/test_tag_db.py | 30 +++++++++++++++---- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/tribler-core/tribler_core/components/metadata_store/remote_query_community/tests/test_remote_search_by_tags.py b/src/tribler-core/tribler_core/components/metadata_store/remote_query_community/tests/test_remote_search_by_tags.py index e87916602f1..09e83b61511 100644 --- a/src/tribler-core/tribler_core/components/metadata_store/remote_query_community/tests/test_remote_search_by_tags.py +++ b/src/tribler-core/tribler_core/components/metadata_store/remote_query_community/tests/test_remote_search_by_tags.py @@ -91,7 +91,7 @@ def fill_tags_database(): Tag(name='tag1', count=SHOW_THRESHOLD), ], b'infohash2': [ - Tag(name='tag2', count=SHOW_THRESHOLD - 1), + Tag(name='tag1', count=SHOW_THRESHOLD - 1), ] }) @@ -110,7 +110,7 @@ def _add(infohash): fill_mds() # Then we try to query search for three tags: 'tag1', 'tag2', 'tag3' - parameters = {'first': 0, 'infohash_set': None, 'last': 100, 'tags': ['tag1', 'tag2', 'tag3']} + parameters = {'first': 0, 'infohash_set': None, 'last': 100, 'tags': ['tag1']} json = dumps(parameters).encode('utf-8') with db_session: diff --git a/src/tribler-core/tribler_core/components/tag/db/tag_db.py b/src/tribler-core/tribler_core/components/tag/db/tag_db.py index 9ee559f0983..be7f58cd247 100644 --- a/src/tribler-core/tribler_core/components/tag/db/tag_db.py +++ b/src/tribler-core/tribler_core/components/tag/db/tag_db.py @@ -3,7 +3,7 @@ from typing import Callable, List, Optional, Set from pony import orm -from pony.orm import select +from pony.orm import exists, select from pony.utils import between from tribler_core.components.tag.community.tag_payload import TagOperation, TagOperationEnum @@ -191,10 +191,24 @@ def show_suggestions_condition(torrent_tag): return self._get_tags(infohash, show_suggestions_condition) def get_infohashes(self, tags: Set[str]) -> List[bytes]: - """Get list of infohashes that belongs to the tag. Only tags with condition `_show_condition` will be returned + """Get list of infohashes that belongs to the tag. + Only tags with condition `_show_condition` will be returned. + In the case that the tags set contains more than one tag, + only torrents that contain all `tags` will be returned. """ - return select(tt.torrent.infohash for tt in self.instance.TorrentTag - if self._show_condition(tt) and tt.tag.name in tags).fetch() + query_results = select( + torrent.infohash for torrent in self.instance.Torrent + if not exists( + tag for tag in self.instance.Tag + if tag.name in tags and not exists( + torrent_tag for torrent_tag in self.instance.TorrentTag + if torrent_tag.torrent == torrent + and torrent_tag.tag == tag + and self._show_condition(torrent_tag) + ) + ) + ).fetch() + return query_results def get_clock(self, operation: TagOperation) -> int: """ Get the clock (int) of operation. diff --git a/src/tribler-core/tribler_core/components/tag/db/tests/test_tag_db.py b/src/tribler-core/tribler_core/components/tag/db/tests/test_tag_db.py index dba25aba105..439b6324fb0 100644 --- a/src/tribler-core/tribler_core/components/tag/db/tests/test_tag_db.py +++ b/src/tribler-core/tribler_core/components/tag/db/tests/test_tag_db.py @@ -348,27 +348,47 @@ async def test_get_tags_operations_for_gossip(self): # assert that only one torrent returned (the old and the not auto generated one) assert len(self.db.get_tags_operations_for_gossip(time_delta)) == 1 + @db_session + async def test_get_infohashes_threshold(self): + # test that `get_infohashes` function returns only infohashes with tags + # above the threshold + self.add_operation_set( + self.db, + { + b'infohash1': [ + Tag(name='tag1', count=SHOW_THRESHOLD), + ], + b'infohash2': [ + Tag(name='tag1', count=SHOW_THRESHOLD - 1) + ] + } + ) + + assert self.db.get_infohashes({'tag1'}) == [b'infohash1'] + @db_session async def test_get_infohashes(self): + # test that `get_infohashes` function returns an intersection of result + # in case of more than one tag passed to the function self.add_operation_set( self.db, { b'infohash1': [ Tag(name='tag1', count=SHOW_THRESHOLD), - Tag(name='tag2', count=SHOW_THRESHOLD - 1) + Tag(name='tag2', count=SHOW_THRESHOLD) ], b'infohash2': [ Tag(name='tag1', count=SHOW_THRESHOLD) ], b'infohash3': [ - Tag(name='tag1', count=SHOW_THRESHOLD - 1) + Tag(name='tag2', count=SHOW_THRESHOLD) ] } ) - # test that only tags above the threshold are associated with infohases - assert self.db.get_infohashes('tag1') == [b'infohash1', b'infohash2'] - assert not self.db.get_infohashes('tag2') + assert self.db.get_infohashes({'tag1'}) == [b'infohash1', b'infohash2'] + assert self.db.get_infohashes({'tag2'}) == [b'infohash1', b'infohash3'] + assert self.db.get_infohashes({'tag1', 'tag2'}) == [b'infohash1'] @db_session async def test_show_condition(self):