mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-10-31 22:19:00 +00:00
Merge branch 'main' into production
This commit is contained in:
commit
4501b504ac
1 changed files with 17 additions and 42 deletions
|
@ -4,7 +4,7 @@ from functools import reduce
|
|||
import operator
|
||||
|
||||
from django.contrib.postgres.search import SearchRank, SearchQuery
|
||||
from django.db.models import OuterRef, Subquery, F, Q
|
||||
from django.db.models import F, Q
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm import connectors
|
||||
|
@ -17,8 +17,15 @@ def search(query, min_confidence=0, filters=None, return_first=False):
|
|||
filters = filters or []
|
||||
if not query:
|
||||
return []
|
||||
query = query.strip()
|
||||
|
||||
results = None
|
||||
# first, try searching unqiue identifiers
|
||||
results = search_identifiers(query, *filters, return_first=return_first)
|
||||
# unique identifiers never have spaces, title/author usually do
|
||||
if not " " in query:
|
||||
results = search_identifiers(query, *filters, return_first=return_first)
|
||||
|
||||
# if there were no identifier results...
|
||||
if not results:
|
||||
# then try searching title/author
|
||||
results = search_title_author(
|
||||
|
@ -35,24 +42,10 @@ def isbn_search(query):
|
|||
# If the ISBN has only 9 characters, prepend missing zero
|
||||
query = query.strip().upper().rjust(10, "0")
|
||||
filters = [{f: query} for f in ["isbn_10", "isbn_13"]]
|
||||
results = models.Edition.objects.filter(
|
||||
return models.Edition.objects.filter(
|
||||
reduce(operator.or_, (Q(**f) for f in filters))
|
||||
).distinct()
|
||||
|
||||
# when there are multiple editions of the same work, pick the default.
|
||||
# it would be odd for this to happen.
|
||||
|
||||
default_editions = models.Edition.objects.filter(
|
||||
parent_work=OuterRef("parent_work")
|
||||
).order_by("-edition_rank")
|
||||
results = (
|
||||
results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter(
|
||||
default_id=F("id")
|
||||
)
|
||||
or results
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def format_search_result(search_result):
|
||||
"""convert a book object into a search result object"""
|
||||
|
@ -88,22 +81,7 @@ def search_identifiers(query, *filters, return_first=False):
|
|||
results = models.Edition.objects.filter(
|
||||
*filters, reduce(operator.or_, (Q(**f) for f in or_filters))
|
||||
).distinct()
|
||||
if results.count() <= 1:
|
||||
if return_first:
|
||||
return results.first()
|
||||
return results
|
||||
|
||||
# when there are multiple editions of the same work, pick the default.
|
||||
# it would be odd for this to happen.
|
||||
default_editions = models.Edition.objects.filter(
|
||||
parent_work=OuterRef("parent_work")
|
||||
).order_by("-edition_rank")
|
||||
results = (
|
||||
results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter(
|
||||
default_id=F("id")
|
||||
)
|
||||
or results
|
||||
)
|
||||
if return_first:
|
||||
return results.first()
|
||||
return results
|
||||
|
@ -120,19 +98,16 @@ def search_title_author(query, min_confidence, *filters, return_first=False):
|
|||
)
|
||||
|
||||
# when there are multiple editions of the same work, pick the closest
|
||||
editions_of_work = results.values("parent_work__id").values_list("parent_work__id")
|
||||
editions_of_work = results.values_list("parent_work__id", flat=True).distinct()
|
||||
|
||||
# filter out multiple editions of the same work
|
||||
list_results = []
|
||||
for work_id in set(editions_of_work):
|
||||
editions = results.filter(parent_work=work_id)
|
||||
default = editions.order_by("-edition_rank").first()
|
||||
default_rank = default.rank if default else 0
|
||||
# if mutliple books have the top rank, pick the default edition
|
||||
if default_rank == editions.first().rank:
|
||||
result = default
|
||||
else:
|
||||
result = editions.first()
|
||||
for work_id in set(editions_of_work[:30]):
|
||||
result = (
|
||||
results.filter(parent_work=work_id)
|
||||
.order_by("-rank", "-edition_rank")
|
||||
.first()
|
||||
)
|
||||
|
||||
if return_first:
|
||||
return result
|
||||
|
|
Loading…
Reference in a new issue