2016-06-16 6 views
7

Pracujemy z wyszukiwaniem w django 1.10 i potrzebujemy wyszukiwania w rankingu użytkownika z trygramowym wyszukiwaniem.Połącz trygram z szukaniem w rankingu w django 1.10

Nasz kod jest taka:

def get_queryset(self): 
     search = self.request.GET.get('text', '') 
     vector = SearchVector('name',weight='A', 
      config=settings.SEARCH_LANGS[ 
       settings.LANGUAGE 
      ], 
      ) + SearchVector(
      'content', 
      weight='B', 
      config=settings.SEARCH_LANGS[ 
       settings.LANGUAGE 
      ], 
      ) 
     query = SearchQuery(search) 
     return Article.objects.annotate(
      rank=SearchRank(
       vector, 
       query 
       ), 
      similarity=TrigramSimilarity(
       'name', search 
       ) + TrigramSimilarity(
       'content', search 
       ), 
      ).filter(
      rank__gte=0.3 
      ).filter(
      similarity__gt=0.3 
      ).order_by(
      '-similarity' 
      )[:20] 

ale ten kod nie zwraca żadnych rekordów, bez użycia trygram problemów, Haven, ale w połączeniu między oni nie możemy dostać zapytania.

W jaki sposób połączyć trygram i wyszukiwanie w rankingu w django 1.10?

Odpowiedz

10

Zbadaliśmy dokładniej sposób, w jaki działają wagi wyszukiwania.

Zgodnie z documents można przypisać wagi według pól, a nawet można im przypisać wagi, podobnie możemy użyć filtru trigrams według podobieństwa lub odległości.

Nie należy jednak podawać przykładu użycia tych dwóch elementów i dokładniej zbadać, co zostało zrozumiane, ani też, jak działają wagi.

Trochę logiki mówi nam, że jeśli szukamy wspólnego słowa we wszystkich będziemy wszyscy 0, podobieństwo zmienia się o wiele bardziej niż zakresy, jednak dąży do niższych wartości, które obejmują.

Teraz, wyszukiwanie tekstu, o ile nam wiadomo, odbywa się w oparciu o tekst zawarty w polach, które chcesz filtrować jeszcze bardziej niż w języku, który jest umieszczony w konfiguracji. Przykładem jest umieszczanie tytułów, używany model ma pole tytułu i pole treści, których najczęściej używanymi słowami były how change, przeglądanie ważonych słów (zakresy funkcjonują jako zapytania, dzięki czemu możemy użyć values lub values_list, aby przejrzeć oceny i podobieństwa, które są wartościami liczbowymi, możemy zobaczyć ważone słowa oglądające obiekt wektorowy), zobaczyliśmy, że jeśli przydzielono wagi, 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 ...", oraz wszystkie słowa tego zdania, jeśli były całe i z wagami B; Wnioskujemy, że wyszukiwania są przeprowadzane na podstawie zawartości pól, aby filtrować więcej niż język, w którym konfigurujemy wyszukiwania.

To powiedziawszy, przedstawiamy kod, którego używamy do wszystkiego.

Po pierwsze, musimy użyć Trygramów w zakresie niezbędnym do umożliwienia bazie danych: operacje

from __future__ import unicode_literals 

from django.db import migrations, models 
import django.db.models.deletion 
from django.contrib.postgres.operations import UnaccentExtension 
from django.contrib.postgres.operations import TrigramExtension 

class Migration(migrations.Migration): 

    initial = True 

    dependencies = [ 
    ] 

    operations = [ 
     ... 
     TrigramExtension(), 
     UnaccentExtension(), 

    ] 

przywozie dla migracji z postgres pakietów i uruchomić z dowolnego migracji plików.

Kolejnym krokiem jest zmiana kodu pytanie tak, że filtr zwraca jeden z querys jeśli drugi nie:

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 
      ) + TrigramSimilarity(
       'content', search 
      ), 
     ).filter(Q(rank__gte=0.3) | Q(similarity__gt=0.3)).order_by('-rank')[:20] 

Problem powyższy kod sączyła jedną kwerendę po drugim, i jeśli wybrane słowo nie pojawia się w żadnym z dwóch wyszukiwań, problem jest większy. Używamy obiektu Q do filtrowania przy użyciu złącza OR, więc jeśli jeden z nich nie zwróci żądanej wartości, wyślij drugi w miejscu.

Wystarczy, ale z przyjemnością wyjaśnią szczegółowo, jak te wagi i trygramy działają, aby w pełni wykorzystać tę nową przewagę oferowaną przez najnowszą wersję Django.

+0

Dziękujemy za udostępnienie znalezionego rozwiązania. – Private