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.