From 3b3cea4d70ed438caef22d1c00f9e86b5109c44d Mon Sep 17 00:00:00 2001 From: Roland Date: Thu, 6 Apr 2023 12:52:29 -0600 Subject: [PATCH] Searching for files with both tags, rather than either tag when filtering by tag names. --- modules/videos/test/test_api.py | 17 +++++++++++++---- wrolpi/files/lib.py | 11 ++++++----- wrolpi/files/test/test_lib.py | 13 +++++-------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/modules/videos/test/test_api.py b/modules/videos/test/test_api.py index f29cfd92..bddd9bb0 100644 --- a/modules/videos/test/test_api.py +++ b/modules/videos/test/test_api.py @@ -239,8 +239,15 @@ def test_search_videos(test_client, test_session, video_factory, assert_video_se channel_id=simple_channel.id) vid3: Video = video_factory(upload_date='2022-09-18', with_video_file=True, title='vid3') tag1, tag2 = tag_factory(), tag_factory() + vid1.add_tag(tag1) + + # vid2 has two tags + vid2.add_tag(tag1) + vid2.add_tag(tag2) + vid3.add_tag(tag2) + test_session.commit() assert test_session.query(Video).count() == 3 assert test_session.query(FileGroup).count() == 3 @@ -250,12 +257,14 @@ def test_search_videos(test_client, test_session, video_factory, assert_video_se assert_video_search(assert_total=3, assert_ids=[vid3.id, vid2.id], order_by='-upload_date', limit=2) assert_video_search(assert_total=3, assert_ids=[vid2.id, vid1.id], order_by='-upload_date', limit=2, offset=1) assert_video_search(assert_total=1, assert_ids=[vid2.id], order_by='-upload_date', channel_id=simple_channel.id) - assert_video_search(assert_total=1, assert_ids=[vid1.id], tag_names=[tag1.name]) - assert_video_search(assert_total=1, assert_ids=[vid1.id], tag_names=[tag1.name], limit=1) - assert_video_search(assert_total=2, assert_ids=[vid3.id, vid1.id], tag_names=[tag1.name, tag2.name]) + assert_video_search(assert_total=2, assert_ids=[vid1.id, vid2.id], tag_names=[tag1.name]) + assert_video_search(assert_total=2, assert_ids=[vid3.id, vid2.id], tag_names=[tag2.name]) + assert_video_search(assert_total=2, assert_ids=[vid1.id], tag_names=[tag1.name], limit=1) + # Only vid2 has both tags. + assert_video_search(assert_total=1, assert_ids=[vid2.id], tag_names=[tag1.name, tag2.name]) # No results, no total is returned from the DB. - assert_video_search(assert_total=0, assert_ids=[], tag_names=[tag1.name], offset=1) + assert_video_search(assert_total=0, assert_ids=[], tag_names=[tag1.name], offset=2) # Check all order_by. for order_by in video_lib.VIDEO_ORDERS: diff --git a/wrolpi/files/lib.py b/wrolpi/files/lib.py index 5dc4d6d6..6b53d382 100644 --- a/wrolpi/files/lib.py +++ b/wrolpi/files/lib.py @@ -580,14 +580,15 @@ def tag_names_to_clauses(tags: List[str]): return '', params, '' where_tags = [] + joins = [] for idx, tag_name in enumerate(tags): - where_tags.append(f't.name = %(tag_name{idx})s') + where_tags.append(f't{idx}.name = %(tag_name{idx})s') params[f'tag_name{idx}'] = tag_name - where_tags = ' OR '.join(where_tags) + joins.append(f'LEFT JOIN tag_file tf{idx} ON tf{idx}.file_group_id = fg.id ' + f'LEFT JOIN tag t{idx} ON t{idx}.id = tf{idx}.tag_id') + where_tags = ' AND '.join(where_tags) wheres = f'({where_tags})' - - join = '''LEFT JOIN tag_file tf ON tf.file_group_id = fg.id - LEFT JOIN tag t ON t.id = tf.tag_id''' + join = '\n'.join(joins) return wheres, params, join diff --git a/wrolpi/files/test/test_lib.py b/wrolpi/files/test/test_lib.py index b68d7a06..89d12d81 100644 --- a/wrolpi/files/test/test_lib.py +++ b/wrolpi/files/test/test_lib.py @@ -538,23 +538,20 @@ def test_get_primary_file(test_directory, video_file, srt_file3, example_epub, e assert lib.get_primary_file([example_pdf, example_mobi, example_epub]) == example_epub -COMMON_JOIN = '''LEFT JOIN tag_file tf ON tf.file_group_id = fg.id - LEFT JOIN tag t ON t.id = tf.tag_id''' - - @pytest.mark.parametrize( 'tags,wheres,params,join', [ ( ['one'], - '(t.name = %(tag_name0)s)', + '(t0.name = %(tag_name0)s)', dict(tag_name0='one'), - COMMON_JOIN, + 'LEFT JOIN tag_file tf0 ON tf0.file_group_id = fg.id LEFT JOIN tag t0 ON t0.id = tf0.tag_id', ), ( ['one', 'two'], - '(t.name = %(tag_name0)s OR t.name = %(tag_name1)s)', + '(t0.name = %(tag_name0)s AND t1.name = %(tag_name1)s)', dict(tag_name0='one', tag_name1='two'), - COMMON_JOIN, + 'LEFT JOIN tag_file tf0 ON tf0.file_group_id = fg.id LEFT JOIN tag t0 ON t0.id = tf0.tag_id' + '\nLEFT JOIN tag_file tf1 ON tf1.file_group_id = fg.id LEFT JOIN tag t1 ON t1.id = tf1.tag_id', ), ( [],