Filter list search results to hide already added books

This commit is contained in:
Mouse Reeve 2021-04-26 08:02:30 -07:00
parent 0cb80aeb55
commit 0f6b5cc6be
3 changed files with 19 additions and 12 deletions

View file

@ -67,10 +67,12 @@ def search(query, min_confidence=0.1):
return results return results
def local_search(query, min_confidence=0.1, raw=False): def local_search(query, min_confidence=0.1, raw=False, filters=None):
""" only look at local search results """ """ only look at local search results """
connector = load_connector(models.Connector.objects.get(local=True)) connector = load_connector(models.Connector.objects.get(local=True))
return connector.search(query, min_confidence=min_confidence, raw=raw) return connector.search(
query, min_confidence=min_confidence, raw=raw, filters=filters
)
def isbn_local_search(query, raw=False): def isbn_local_search(query, raw=False):

View file

@ -13,15 +13,16 @@ class Connector(AbstractConnector):
""" instantiate a connector """ """ instantiate a connector """
# pylint: disable=arguments-differ # pylint: disable=arguments-differ
def search(self, query, min_confidence=0.1, raw=False): def search(self, query, min_confidence=0.1, raw=False, filters=None):
""" search your local database """ """ search your local database """
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) results = search_identifiers(query, *filters)
if not results: if not results:
# then try searching title/author # then try searching title/author
results = search_title_author(query, min_confidence) results = search_title_author(query, min_confidence, *filters)
search_results = [] search_results = []
for result in results: for result in results:
if raw: if raw:
@ -98,15 +99,15 @@ class Connector(AbstractConnector):
pass pass
def search_identifiers(query): def search_identifiers(query, *filters):
""" tries remote_id, isbn; defined as dedupe fields on the model """ """ tries remote_id, isbn; defined as dedupe fields on the model """
filters = [ or_filters = [
{f.name: query} {f.name: query}
for f in models.Edition._meta.get_fields() for f in models.Edition._meta.get_fields()
if hasattr(f, "deduplication_field") and f.deduplication_field if hasattr(f, "deduplication_field") and f.deduplication_field
] ]
results = models.Edition.objects.filter( results = models.Edition.objects.filter(
reduce(operator.or_, (Q(**f) for f in filters)) *filters, reduce(operator.or_, (Q(**f) for f in or_filters))
).distinct() ).distinct()
# when there are multiple editions of the same work, pick the default. # when there are multiple editions of the same work, pick the default.
@ -114,7 +115,7 @@ def search_identifiers(query):
return results.filter(parent_work__default_edition__id=F("id")) or results return results.filter(parent_work__default_edition__id=F("id")) or results
def search_title_author(query, min_confidence): def search_title_author(query, min_confidence, *filters):
""" searches for title and author """ """ searches for title and author """
vector = ( vector = (
SearchVector("title", weight="A") SearchVector("title", weight="A")
@ -126,7 +127,7 @@ def search_title_author(query, min_confidence):
results = ( results = (
models.Edition.objects.annotate(search=vector) models.Edition.objects.annotate(search=vector)
.annotate(rank=SearchRank(vector, query)) .annotate(rank=SearchRank(vector, query))
.filter(rank__gt=min_confidence) .filter(*filters, rank__gt=min_confidence)
.order_by("-rank") .order_by("-rank")
) )

View file

@ -137,7 +137,11 @@ class List(View):
if query and request.user.is_authenticated: if query and request.user.is_authenticated:
# search for books # search for books
suggestions = connector_manager.local_search(query, raw=True) suggestions = connector_manager.local_search(
query,
raw=True,
filters=[~Q(parent_work__editions__in=book_list.books.all())],
)
elif request.user.is_authenticated: elif request.user.is_authenticated:
# just suggest whatever books are nearby # just suggest whatever books are nearby
suggestions = request.user.shelfbook_set.filter( suggestions = request.user.shelfbook_set.filter(
@ -265,7 +269,7 @@ def add_book(request):
# if the book is already on the list, don't flip out # if the book is already on the list, don't flip out
pass pass
path = reverse('list', args=[book_list.id]) path = reverse("list", args=[book_list.id])
return redirect("{:s}?{:s}".format(path, urlencode(request.GET))) return redirect("{:s}?{:s}".format(path, urlencode(request.GET)))