PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Combina trigram con la ricerca classificata in django 1.10

Abbiamo studiato in modo più approfondito come funziona la ricerca dei pesi.

Secondo documenti puoi assegnare pesi in base ai campi e possono anche essere assegnati pesi, e allo stesso modo possiamo usare trigrammi per filtrare per somiglianza o distanza.

Tuttavia non specificare un esempio dell'utilizzo dei due e indagare ulteriormente non ha capito né tanto quanto i pesi funzionano.

Un po' di logica ci dice che se cerchiamo una parola comune in tutto saremo tutti di rango 0, la somiglianza varia molto di più degli intervalli, tuttavia tende a valori più bassi di quell'intervallo.

Ora, la ricerca testuale, a quanto ci risulta, viene effettuata in base al testo contenuto nei campi che si desidera filtrare ancor più che nella lingua che si trova nella configurazione. Un esempio è che inserendo i titoli, il modello utilizzato aveva un campo titolo e un campo contenuto, le cui parole più comuni erano how change , rivedendo le parole pesate (gli intervalli funzionano come query, quindi possiamo utilizzare values ​​o values_list per rivedere i ranghi e le somiglianze, che sono valori numerici, possiamo visualizzare le parole pesate visualizzando l'oggetto vettore), abbiamo visto che se fossero stati assegnati pesi, ma combinazioni di parole divise:trovato 'perfil' e 'cambi', tuttavia non abbiamo trovato 'cambiare' o 'como'; tuttavia tutti i modelli contenevano lo stesso testo di 'lorem ipsun...', e tutte le parole di quella frase se erano intere e con pesi B; Concludiamo con ciò che le ricerche vengono effettuate in base al contenuto dei campi per filtrare più della lingua con cui configuriamo le ricerche.

Detto questo, qui presentiamo il codice che utilizziamo per tutto.

Innanzitutto, dobbiamo utilizzare Trigram nella misura necessaria per abilitare il database:

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

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

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

    ]

Operazioni di importazione per la migrazione da postgres pacchetti ed esegui da qualsiasi migrazione di file .

Il passaggio successivo consiste nel modificare il codice della domanda in modo che il filtro restituisca una delle query se la seconda non riesce:

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]

Il problema con il codice sopra era filtrare una query dopo l'altra e se la parola scelta non compare in nessuna delle due ricerche il problema è maggiore. Usiamo una Q oggetto da filtrare utilizzando un OR connettore in modo che se uno dei due non restituisce un valore desiderato, mandi l'altro al suo posto.

Con questo è sufficiente, tuttavia sono graditi chiarimenti approfonditi su come funzionano questi pesi e trigrammi, per esplicitare al meglio questo nuovo vantaggio offerto dall'ultima versione di Django.