PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Kombiniere Trigram mit Ranglistensuche in Django 1.10

Wir haben genauer untersucht, wie die Suche funktioniert und wie Gewichtungen funktionieren.

Laut Dokumenten Ihnen können Gewichtungen gemäß den Feldern zugewiesen werden und ihnen können sogar Gewichtungen zugewiesen werden, und ähnlich können wir Trigramme um nach Ähnlichkeit oder Entfernung zu filtern.

Geben Sie jedoch kein Beispiel für die Verwendung der beiden an und untersuchen Sie es weiter, und verstehen Sie nicht viel davon, wie Gewichte funktionieren

Ein wenig Logik sagt uns, dass, wenn wir ein gemeinsames Wort in allen suchen, wir alle auf 0 rangieren, die Ähnlichkeit viel stärker variiert als die Bereiche, jedoch tendenziell niedrigere Werte in diesem Bereich.

Jetzt wird die Textsuche, soweit wir verstehen, basierend auf dem Text durchgeführt, der in den Feldern enthalten ist, die Sie filtern möchten, noch mehr als in der Sprache, die in der Konfiguration platziert ist. Beispiel:Das verwendete Modell zum Setzen von Titeln hatte ein Titelfeld und ein Inhaltsfeld, deren häufigste Wörter how change waren , Überprüfung gewichteter Wörter (Bereiche fungieren als Abfrage, sodass wir values verwenden können ​​oder values_list Um die Ränge und Ähnlichkeiten zu überprüfen, bei denen es sich um numerische Werte handelt, können wir gewichtete Wörter anzeigen, wenn wir das Vektorobjekt anzeigen), haben wir gesehen, dass, wenn Gewichtungen zugewiesen wurden, aber Kombinationen von geteilten Wörtern:'perfil' und 'cambi' gefunden wurden, jedoch nicht gefunden wurden 'cambiar' oder 'como'; jedoch hatten alle Modelle denselben Text wie „lorem ipsun ...“ und alle Wörter dieses Satzes enthalten, wenn sie ganz und mit Gewichten B waren; Wir schließen daraus, dass die Suche auf der Grundlage des Inhalts der Felder erfolgt, um mehr zu filtern als auf der Sprache, mit der wir Suchen konfigurieren.

Trotzdem präsentieren wir hier den Code, den wir für alles verwenden.

Zuerst müssen wir Trigrams in dem Umfang verwenden, der notwendig ist, um die Datenbank zu aktivieren:

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

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

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

    ]

Importvorgänge für die Migration von postgres Pakete und laufen von jeder Dateimigration .

Der nächste Schritt besteht darin, den Code der Frage so zu ändern, dass der Filter eine der Abfragen zurückgibt, wenn die zweite fehlschlägt:

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]

Das Problem mit dem obigen Code bestand darin, dass eine Abfrage nach der anderen durchsickerte, und wenn das ausgewählte Wort in keiner der beiden Suchen auftauchte, war das Problem größer . Wir verwenden ein Q Objekt, das mit einem OR gefiltert werden soll Konnektor, damit, wenn einer der beiden keinen gewünschten Wert zurückgibt, der andere stattdessen gesendet wird.

Dies reicht aus, aber sie sind willkommene Erläuterungen zur Funktionsweise dieser Gewichte und Trigramme, um das Beste aus diesem neuen Vorteil herauszuholen, den die neueste Version von Django bietet.