Updates first_search_result functionality

This commit is contained in:
Mouse Reeve 2021-09-16 11:07:36 -07:00
parent 76ab5a763c
commit fbe05623ff
2 changed files with 24 additions and 9 deletions

View file

@ -11,16 +11,18 @@ from bookwyrm.settings import MEDIA_FULL_URL
# pylint: disable=arguments-differ # pylint: disable=arguments-differ
def search(query, min_confidence=0, filters=None): def search(query, min_confidence=0, filters=None, return_first=False):
"""search your local database""" """search your local database"""
filters = filters or [] filters = filters or []
if not query: if not query:
return [] return []
# first, try searching unqiue identifiers # first, try searching unqiue identifiers
results = search_identifiers(query, *filters) results = search_identifiers(query, *filters, return_first=return_first)
if not results: if not results:
# then try searching title/author # then try searching title/author
results = search_title_author(query, min_confidence, *filters) results = search_title_author(
query, min_confidence, *filters, return_first=return_first
)
return results return results
@ -68,7 +70,7 @@ def format_search_result(search_result):
).json() ).json()
def search_identifiers(query, *filters): def search_identifiers(query, *filters, return_first=False):
"""tries remote_id, isbn; defined as dedupe fields on the model""" """tries remote_id, isbn; defined as dedupe fields on the model"""
# pylint: disable=W0212 # pylint: disable=W0212
or_filters = [ or_filters = [
@ -87,15 +89,18 @@ def search_identifiers(query, *filters):
default_editions = models.Edition.objects.filter( default_editions = models.Edition.objects.filter(
parent_work=OuterRef("parent_work") parent_work=OuterRef("parent_work")
).order_by("-edition_rank") ).order_by("-edition_rank")
return ( results = (
results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter( results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter(
default_id=F("id") default_id=F("id")
) )
or results or results
) )
if return_first:
return results.first()
return results
def search_title_author(query, min_confidence, *filters): def search_title_author(query, min_confidence, *filters, return_first=False):
"""searches for title and author""" """searches for title and author"""
query = SearchQuery(query, config="simple") | SearchQuery(query, config="english") query = SearchQuery(query, config="simple") | SearchQuery(query, config="english")
results = ( results = (
@ -109,12 +114,17 @@ def search_title_author(query, min_confidence, *filters):
editions_of_work = results.values("parent_work__id").values_list("parent_work__id") editions_of_work = results.values("parent_work__id").values_list("parent_work__id")
# filter out multiple editions of the same work # filter out multiple editions of the same work
results = []
for work_id in set(editions_of_work): for work_id in set(editions_of_work):
editions = results.filter(parent_work=work_id) editions = results.filter(parent_work=work_id)
default = editions.order_by("-edition_rank").first() default = editions.order_by("-edition_rank").first()
default_rank = default.rank if default else 0 default_rank = default.rank if default else 0
# if mutliple books have the top rank, pick the default edition # if mutliple books have the top rank, pick the default edition
if default_rank == editions.first().rank: if default_rank == editions.first().rank:
yield default result = default
else: else:
yield editions.first() result = editions.first()
if return_first:
return result
results.append(result)
return results

View file

@ -10,7 +10,7 @@ from django.db.models import signals
from requests import HTTPError from requests import HTTPError
from bookwyrm import models from bookwyrm import book_search, models
from bookwyrm.tasks import app from bookwyrm.tasks import app
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -73,6 +73,11 @@ def search(query, min_confidence=0.1, return_first=False):
def first_search_result(query, min_confidence=0.1): def first_search_result(query, min_confidence=0.1):
"""search until you find a result that fits""" """search until you find a result that fits"""
# try local search first
result = book_search.search(query, min_confidence=min_confidence, return_first=True)
if result:
return result
# otherwise, try remote endpoints
return search(query, min_confidence=min_confidence, return_first=True) or None return search(query, min_confidence=min_confidence, return_first=True) or None