Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-tag search API #705

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions files/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
from .stop_words import STOP_WORDS
from .tasks import save_user_action

OR_KEYWORD = "-OR"

VALID_USER_ACTIONS = [action for action, name in USER_MEDIA_ACTIONS]


Expand Down Expand Up @@ -744,7 +746,21 @@ def get(self, request, format=None):
params = self.request.query_params
query = params.get("q", "").strip().lower()
category = params.get("c", "").strip()
tag = params.get("t", "").strip()
tag_query = params.get("t", "").strip()
search_tags = []
flip_tag_and_to_or = False
if tag_query:
search_tags = tag_query.split(',')
if len(search_tags) > 0:
search_tags = set(search_tags)
search_tags.discard('')
if OR_KEYWORD in search_tags:
flip_tag_and_to_or = True
search_tags.remove(OR_KEYWORD)
search_tags = list(search_tags)
tag = False
if len(search_tags) > 0:
tag = True

ordering = params.get("ordering", "").strip()
sort_by = params.get("sort_by", "").strip()
Expand Down Expand Up @@ -784,7 +800,38 @@ def get(self, request, format=None):
media = media.filter(search=query)

if tag:
media = media.filter(tags__title=tag)
if len(search_tags) > 1:
# multi-tag cases to handle
# 1. none exist http://localhost/search?t=t,g,d
# 2. one exists http://localhost/search?t=VALID,g,d
# 3. all empty http://localhost/search?t=,,,
# 4. some empty http://localhost/search?t=,VALID
# ......... http://localhost/search?t=VALID,
# ......... http://localhost/search?t=VALID,,ANOTHER
# 5. all exist http://localhost/search?t=VALID,ANOTHER
# 6. DUPES http://localhost/search?t=VALID,VALID
# 7. Just OR http://localhost/search?t=OR
# ....... http://localhost/search?t=OR,
if flip_tag_and_to_or:
media = media.filter(tags__title__in=search_tags).distinct()
else:
found_tags = []
for addtl_tag in search_tags:
if addtl_tag:
try:
found = Tag.objects.get(title=addtl_tag)
except Tag.DoesNotExist:
found = None
if found:
found_tags.append(found)
if len(found_tags) == 0:
ret = {}
return Response(ret, status=status.HTTP_200_OK)
else:
for found_tag in found_tags:
media = media.filter(tags__title=found_tag)
else:
media = media.filter(tags__title=search_tags[0])

if category:
media = media.filter(category__title__contains=category)
Expand Down