From 856c34a3bfb87dd3655ad2158b713e8b4956a02b Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Tue, 28 Sep 2021 19:12:51 +0200 Subject: [PATCH] fixed and expanded on trigram search --- cookbook/forms.py | 8 +-- cookbook/helper/recipe_search.py | 7 ++- ...0156_searchpreference_trigram_threshold.py | 18 +++++++ cookbook/models.py | 1 + cookbook/templates/settings.html | 54 ++++++++++++------- cookbook/views/views.py | 1 + 6 files changed, 62 insertions(+), 27 deletions(-) create mode 100644 cookbook/migrations/0156_searchpreference_trigram_threshold.py diff --git a/cookbook/forms.py b/cookbook/forms.py index 3ea7300d7..4b119199f 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -1,7 +1,7 @@ from django import forms from django.conf import settings from django.core.exceptions import ValidationError -from django.forms import widgets +from django.forms import widgets, NumberInput from django.utils.translation import gettext_lazy as _ from django_scopes import scopes_disabled from django_scopes.forms import SafeModelChoiceField, SafeModelMultipleChoiceField @@ -390,10 +390,12 @@ class UserCreateForm(forms.Form): class SearchPreferenceForm(forms.ModelForm): prefix = 'search' + trigram_threshold = forms.DecimalField(min_value=0.01, max_value=1, decimal_places=2, widget=NumberInput(attrs={'class': "form-control-range", 'type': 'range'}), + help_text=_('Determines how fuzzy a search is if it uses trigram similarity matching (e.g. low values mean more typos are ignored).')) class Meta: model = SearchPreference - fields = ('search', 'lookup', 'unaccent', 'icontains', 'istartswith', 'trigram', 'fulltext') + fields = ('search', 'lookup', 'unaccent', 'icontains', 'istartswith', 'trigram', 'fulltext', 'trigram_threshold') help_texts = { 'search': _('Select type method of search. Click here for full desciption of choices.'), @@ -402,7 +404,7 @@ class SearchPreferenceForm(forms.ModelForm): 'icontains': _("Fields to search for partial matches. (e.g. searching for 'Pie' will return 'pie' and 'piece' and 'soapie')"), 'istartswith': _("Fields to search for beginning of word matches. (e.g. searching for 'sa' will return 'salad' and 'sandwich')"), 'trigram': _("Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) Note: this option will conflict with 'web' and 'raw' methods of search."), - 'fulltext': _("Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods only function with fulltext fields.") + 'fulltext': _("Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods only function with fulltext fields."), } labels = { diff --git a/cookbook/helper/recipe_search.py b/cookbook/helper/recipe_search.py index 5a8851180..bd1c0ba38 100644 --- a/cookbook/helper/recipe_search.py +++ b/cookbook/helper/recipe_search.py @@ -112,16 +112,15 @@ def search_recipes(request, queryset, params): ) # iterate through fields to use in trigrams generating a single trigram - if search_trigram & len(trigram_include) > 1: + if search_trigram and len(trigram_include) > 0: trigram = None for f in trigram_include: if trigram: trigram += TrigramSimilarity(f, search_string) else: trigram = TrigramSimilarity(f, search_string) - queryset.annotate(simularity=trigram) - # TODO allow user to play with trigram scores - filters += [Q(simularity__gt=0.5)] + queryset = queryset.annotate(similarity=trigram) + filters += [Q(similarity__gt=search_prefs.trigram_threshold)] if 'name' in fulltext_include: filters += [Q(name_search_vector=search_query)] diff --git a/cookbook/migrations/0156_searchpreference_trigram_threshold.py b/cookbook/migrations/0156_searchpreference_trigram_threshold.py new file mode 100644 index 000000000..23d925ea3 --- /dev/null +++ b/cookbook/migrations/0156_searchpreference_trigram_threshold.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.7 on 2021-09-28 16:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0155_mealtype_default'), + ] + + operations = [ + migrations.AddField( + model_name='searchpreference', + name='trigram_threshold', + field=models.DecimalField(decimal_places=2, default=0.1, max_digits=3), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index 62c8dc9b3..cc085f6e9 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -873,6 +873,7 @@ class SearchPreference(models.Model, PermissionModelMixin): istartswith = models.ManyToManyField(SearchFields, related_name="istartswith_fields", blank=True) trigram = models.ManyToManyField(SearchFields, related_name="trigram_fields", blank=True) fulltext = models.ManyToManyField(SearchFields, related_name="fulltext_fields", blank=True) + trigram_threshold = models.DecimalField(default=0.1, decimal_places=2, max_digits=3) class UserFile(ExportModelOperationsMixin('user_files'), models.Model, PermissionModelMixin): diff --git a/cookbook/templates/settings.html b/cookbook/templates/settings.html index 7ca106089..0cb63e645 100644 --- a/cookbook/templates/settings.html +++ b/cookbook/templates/settings.html @@ -21,27 +21,31 @@