Zbadaliśmy dokładniej, jak działa wyszukiwanie, wagi.
Według dokumenty można przypisać wagi zgodnie z polami, a nawet można im przypisać wagi, i podobnie możemy użyć trygramy filtrować według podobieństwa lub odległości.
Jednak nie podawaj przykładu użycia tych dwóch i dalszego badania, które to zrozumiałe, ani jak działają wagi.
Trochę logiki podpowiada nam, że jeśli szukamy wspólnego słowa we wszystkich, wszyscy będziemy mieć rangę 0, podobieństwo różni się znacznie bardziej niż zakresy, jednak dążymy do niższych wartości tego zakresu.
Teraz wyszukiwanie tekstowe, o ile rozumiemy, odbywa się na podstawie tekstu zawartego w polach, które chcesz filtrować nawet bardziej niż w języku, który jest umieszczony w konfiguracji. Przykładem jest to, że umieszczając tytuły, używany model miał pole tytułu i pole treści, których najczęstszymi słowami były how change
, przeglądanie ważonych słów (zakresy działają jak zapytania, więc możemy użyć values
lub values_list
aby przejrzeć rangi i podobieństwa, które są wartościami liczbowymi, możemy wyświetlić ważone słowa przeglądając obiekt wektorowy), widzieliśmy, że jeśli wagi zostały przydzielone, ale kombinacje podzielonych słów:znaleziono 'perfil' i 'cambi', jednak nie znaleźliśmy „cambiar” lub „como”; jednak wszystkie modele zawierały ten sam tekst co 'lorem ipsun...' i wszystkie słowa tego zdania, jeśli były całe iz wagami B; Konkludujemy na tym, że wyszukiwania są wykonywane na podstawie zawartości pól, aby filtrować więcej niż język, w którym konfigurujemy wyszukiwania.
To powiedziawszy, tutaj przedstawiamy kod, którego używamy do wszystkiego.
Najpierw musimy użyć Trigramów w zakresie niezbędnym do włączenia bazy danych:
from django.db import migrations
from django.contrib.postgres.operations import UnaccentExtension, TrigramExtension
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
...
TrigramExtension(),
UnaccentExtension(),
]
Operacje importu do migracji z postgres
pakiety i uruchamiane z dowolnej migracji plików.
Następnym krokiem jest zmiana kodu pytania tak, aby filtr zwracał jedno z zapytań, jeśli drugie się nie powiedzie:
def get_queryset(self):
search_query = SearchQuery(self.request.GET.get('q', ''))
vector = SearchVector(
'name',
weight='A',
config=settings.SEARCH_LANGS[settings.LANGUAGE_CODE],
) + SearchVector(
'content',
weight='B',
config=settings.SEARCH_LANGS[settings.LANGUAGE_CODE],
)
if self.request.user.is_authenticated:
queryset = Article.actives.all()
else:
queryset = Article.publics.all()
return queryset.annotate(
rank=SearchRank(vector, search_query)
similarity=TrigramSimilarity(
'name', search_query
) + TrigramSimilarity(
'content', search_query
),
).filter(Q(rank__gte=0.3) | Q(similarity__gt=0.3)).order_by('-rank')[:20]
Problem z powyższym kodem polegał na przenikaniu jednego zapytania po drugim, a jeśli wybrane słowo nie pojawia się w żadnym z dwóch wyszukiwań, problem jest większy . Używamy Q
obiekt do filtrowania za pomocą OR
złącze tak, że jeśli jeden z dwóch nie zwróci pożądanej wartości, wyślij drugi na miejsce.
To wystarczy, jednak mile widziane są szczegółowe wyjaśnienia dotyczące działania tych wag i trigramów, aby w pełni wykorzystać tę nową zaletę oferowaną przez najnowszą wersję Django.