PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Combine trigrama com pesquisa classificada no django 1.10


Investigamos mais profundamente entendido como a pesquisa funciona pesos.

De acordo com documentos você pode receber pesos de acordo com os campos e eles podem até receber pesos, e da mesma forma podemos usar trigramas filtrar por similaridade ou distância.

No entanto, não especifique um exemplo de usar os dois e investigar mais a fundo, nem entender como os pesos funcionam.

Um pouco de lógica nos diz que se buscarmos uma palavra comum em todos vamos todos os ranks 0, a similaridade varia muito mais do que os ranges, porém tende a valores menores desse range.

Agora, a pesquisa de texto, pelo que entendemos, é realizada com base no texto contido nos campos que você deseja filtrar ainda mais do que no idioma que é colocado na configuração. Exemplo é que colocando títulos, o modelo utilizado tinha um campo de título e um campo de conteúdo, cujas palavras mais comuns eram how change , revisando palavras ponderadas (os intervalos funcionam como consulta, para que possamos usar values ​​ou values_list para rever os ranks e semelhanças, que são valores numéricos, podemos visualizar palavras ponderadas visualizando objeto vetorial), vimos que se os pesos fossem alocados, mas combinações de palavras divididas:encontramos 'perfil' e 'cambi', porém não encontramos 'cambiar' ou 'como'; no entanto, todos os modelos continham o mesmo texto que 'lorem ipsun...', e todas as palavras dessa frase se fossem inteiras e com pesos B; Concluímos com isso que as pesquisas são feitas com base no conteúdo dos campos para filtrar mais do que o idioma com o qual configuramos as pesquisas.

Dito isso, aqui apresentamos o código que usamos para tudo.

Primeiro, precisamos usar Trigrams na extensão necessária para habilitar o banco de dados:
from django.db import migrations
from django.contrib.postgres.operations import UnaccentExtension, TrigramExtension

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

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

    ]

Importar operações para migração de postgres pacotes e executados a partir de qualquer migração de arquivos.

O próximo passo é alterar o código da pergunta para que o filtro retorne uma das consultas caso a segunda falhe:
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]

O problema com o código acima era vazar uma consulta atrás da outra, e se a palavra escolhida não aparecer em nenhuma das duas buscas o problema é maior. Usamos um Q objeto para filtrar usando um OR conector para que, caso um dos dois não retorne um valor desejado, envie o outro no local.

Com isso basta, porém são bem vindos esclarecimentos aprofundados sobre como funcionam esses pesos e trigramas, para explorar ao máximo essa nova vantagem oferecida pela última versão do Django.