Neil  Morgan

Neil Morgan

1660498920

Pesquisa Básica E De Texto Completo Com Django E Postgres

Ao contrário dos bancos de dados relacionais, a pesquisa de texto completo não é padronizada. Existem várias opções de código aberto, como ElasticSearch, Solr e Xapian. O ElasticSearch é provavelmente a solução mais popular; no entanto, é complicado de configurar e manter. Além disso, se você não estiver aproveitando alguns dos recursos avançados que o ElasticSearch oferece, você deve ficar com os recursos de pesquisa de texto completo que muitos bancos de dados relacionais (como Postgres, MySQL, SQLite) e não relacionais (como MongoDB e CouchDB ) oferta. O Postgres, em particular, é adequado para pesquisa de texto completo. O Django também oferece suporte pronto para uso.

Para a grande maioria de seus aplicativos Django, você deve, no mínimo, começar aproveitando a pesquisa de texto completo do Postgres antes de procurar uma solução mais poderosa como ElasticSearch ou Solr.

Neste tutorial, você aprenderá como adicionar pesquisa básica e de texto completo a um aplicativo Django com o Postgres. Você também otimizará a pesquisa de texto completo adicionando um campo de vetor de pesquisa e um índice de banco de dados.

Objetivos

Ao final deste tutorial, você será capaz de:

  1. Configure a funcionalidade de pesquisa básica em um aplicativo Django com o módulo de objeto Q
  2. Adicionar pesquisa de texto completo a um aplicativo Django
  3. Classifique os resultados da pesquisa de texto completo por relevância usando técnicas de lematização, classificação e ponderação
  4. Adicione uma visualização aos seus resultados de pesquisa
  5. Otimize a pesquisa de texto completo com um campo de vetor de pesquisa e um índice de banco de dados

Configuração e visão geral do projeto

Clone o branch base do repositório django-search :

$ git clone https://github.com/testdrivenio/django-search --branch base --single-branch
$ cd django-search

Você usará o Docker para simplificar a configuração e execução do Postgres junto com o Django.

Na raiz do projeto, crie as imagens e ative os contêineres do Docker:

$ docker-compose up -d --build

Em seguida, aplique as migrações e crie um superusuário:

$ docker-compose exec web python manage.py makemigrations
$ docker-compose exec web python manage.py migrate
$ docker-compose exec web python manage.py createsuperuser

Depois de concluído, navegue até http://127.0.0.1:8011/quotes/ para garantir que o aplicativo funcione conforme o esperado. Você deve ver o seguinte:

Página inicial de cotação

Quer aprender a trabalhar com Django e Postgres? Confira o artigo Dockerizing Django com Postgres, Gunicorn e Nginx .

Anote o Quotemodelo em quotes/models.py :

from django.db import models

class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)

    def __str__(self):
        return self.quote

Em seguida, execute o seguinte comando de gerenciamento para adicionar 10.000 cotações ao banco de dados:

$ docker-compose exec web python manage.py add_quotes

Isso levará alguns minutos. Uma vez feito, navegue até http://127.0.0.1:8011/quotes/ para ver os dados.

A saída da visualização é armazenada em cache por cinco minutos, portanto, você pode comentar @method_decoratorem quotes/views.py para carregar as aspas. Certifique-se de remover o comentário uma vez feito.

Página inicial de cotação

No arquivo quotes/templates/quote.html , você tem um formulário básico com um campo de entrada de pesquisa:

<form action="{% url 'search_results' %}" method="get">
  <input
    type="search"
    name="q"
    placeholder="Search by name or quote..."
    class="form-control"
  />
</form>

Ao enviar, o formulário envia os dados para o back-end. Uma GETsolicitação é usada em vez de uma POSTpara que tenhamos acesso à string de consulta tanto na URL quanto na visualização do Django, permitindo que os usuários compartilhem os resultados da pesquisa como links.

Antes de prosseguir, dê uma olhada rápida na estrutura do projeto e no restante do código.

Pesquisa básica

Quando se trata de pesquisa, com o Django, você normalmente começará realizando consultas de pesquisa com containsou icontainspara correspondências exatas. O objeto Q também pode ser usado para adicionar operadores lógicos AND ( &) ou OR ( ).|

Por exemplo, usando o operador OR, substitua o SearchResultsListpadrão de 's QuerySetem quotes/views.py assim:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(
            Q(name__icontains=query) | Q(quote__icontains=query)
        )

Aqui, usamos o método de filtro para filtrar os campos ou name. quoteAlém disso, também usamos a extensão icontains para verificar se a consulta está presente nos campos nameou quote(não diferencia maiúsculas de minúsculas). Um resultado positivo será retornado se uma correspondência for encontrada.

Não esqueça da importação:

from django.db.models import Q

Experimente:

Página de pesquisa

Para conjuntos de dados pequenos, essa é uma ótima maneira de adicionar funcionalidades básicas de pesquisa ao seu aplicativo. Se você estiver lidando com um grande conjunto de dados ou quiser uma funcionalidade de pesquisa que pareça um mecanismo de pesquisa da Internet, convém mudar para a pesquisa de texto completo.

Pesquisa de texto completo

A pesquisa básica que vimos anteriormente tem várias limitações, especialmente quando você deseja realizar pesquisas complexas.

Como mencionado, com a pesquisa básica, você só pode realizar correspondências exatas.

Outra limitação é a das palavras de parada . Palavras de parada são palavras como "a", "an" e "the". Essas palavras são comuns e pouco significativas, portanto, devem ser ignoradas. Para testar, tente pesquisar uma palavra com "the" na frente. Digamos que você pesquisou por "no meio". Nesse caso, você verá apenas resultados para "o meio", portanto não verá resultados que tenham a palavra "meio" sem "o" antes dela.

Digamos que você tenha essas duas frases:

  1. Eu estou no meio.
  2. Você não gosta do ensino médio.

Você obterá o seguinte retorno com cada tipo de pesquisa:

ConsultaPesquisa básicaPesquisa de texto completo
"o meio"primeiro1 e 2
"meio"1 e 21 e 2

Outra questão é a de ignorar palavras semelhantes. Com a pesquisa básica, apenas as correspondências exatas são retornadas. No entanto, com a pesquisa de texto completo, palavras semelhantes são contabilizadas. Para testar, tente encontrar algumas palavras semelhantes como "pônei" e "pôneis". Com a pesquisa básica, se você pesquisar por "pônei", não verá resultados que contenham "pôneis" - e vice-versa.

Digamos que você tenha essas duas frases.

  1. Eu sou um pônei.
  2. Você não gosta de pôneis

Você obterá o seguinte retorno com cada tipo de pesquisa:

ConsultaPesquisa básicaPesquisa de texto completo
"pónei"primeiro1 e 2
"pôneis"21 e 2

Com a pesquisa de texto completo, esses dois problemas são atenuados. No entanto, lembre-se de que, dependendo do seu objetivo, a pesquisa de texto completo pode diminuir a precisão (qualidade) e a recuperação (quantidade de resultados relevantes). Normalmente, a pesquisa de texto completo é menos precisa do que a pesquisa básica, pois a pesquisa básica produz correspondências exatas. Dito isso, se você estiver pesquisando em grandes conjuntos de dados com grandes blocos de texto, a pesquisa de texto completo é preferível, pois geralmente é muito mais rápida.

A pesquisa de texto completo é uma técnica de pesquisa avançada que examina todas as palavras em cada documento armazenado enquanto tenta corresponder aos critérios de pesquisa. Além disso, com a pesquisa de texto completo, você pode empregar derivação específica do idioma nas palavras que estão sendo indexadas. Por exemplo, as palavras "drives", "drive" e "driven" serão registradas sob a palavra de conceito único "drive". Stemming é o processo de reduzir palavras à sua raiz, base ou forma de raiz.

Basta dizer que a pesquisa de texto completo não é perfeita. É provável que recupere muitos documentos que não são relevantes (falsos positivos) para a consulta de pesquisa pretendida. No entanto, existem algumas técnicas baseadas em algoritmos Bayesianos que podem ajudar a reduzir tais problemas.

Para aproveitar a pesquisa de texto completo do Postgres com o Django, adicione django.contrib.postgresà sua INSTALLED_APPSlista:

INSTALLED_APPS = [
    ...

    "django.contrib.postgres",  # new
]

Em seguida, vamos ver dois exemplos rápidos de pesquisa de texto completo, em um único campo e em vários campos.

Pesquisa de campo único

Atualize a get_querysetfunção na função de SearchResultsListvisualização da seguinte forma:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(quote__search=query)

Aqui, configuramos a pesquisa de texto completo em um único campo -- o campo de cotação.

Página de pesquisa

Como você pode ver, leva em consideração palavras semelhantes. No exemplo acima, "pôneis" e "pônei" são tratados como palavras semelhantes.

Pesquisa de vários campos

Para pesquisar em vários campos e em modelos relacionados, você pode usar a SearchVectorclasse.

Novamente, atualize SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.annotate(search=SearchVector("name", "quote")).filter(
            search=query
        )

Para pesquisar em vários campos, você anota o conjunto de consultas usando um SearchVector. O vetor são os dados que você está procurando, que foram convertidos em um formulário fácil de pesquisar. No exemplo acima, esses dados são os campos namee em seu banco de dados.quote

Certifique-se de adicionar a importação:

from django.contrib.postgres.search import SearchVector

Tente algumas pesquisas.

Derivação e classificação

Nesta seção, você combinará vários métodos, como SearchVector , SearchQuery e SearchRank para produzir uma pesquisa muito robusta que usa lematização e classificação.

Novamente, stemming é o processo de reduzir palavras ao seu radical, base ou raiz. Com a derivação, palavras como "criança" e "crianças" serão tratadas como palavras semelhantes. O ranking, por outro lado, nos permite ordenar os resultados por relevância.

Atualização SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", "quote")
        search_query = SearchQuery(query)
        return (
            Quote.objects.annotate(
                search=search_vector, rank=SearchRank(search_vector, search_query)
            )
            .filter(search=search_query)
            .order_by("-rank")
        )

O que está acontecendo aqui?

  1. SearchVector- novamente você usou um vetor de pesquisa para pesquisar em vários campos. Os dados são convertidos em outro formulário, pois você não está mais apenas pesquisando o texto bruto como fazia quando icontainsera usado. Portanto, com isso, você poderá pesquisar plurais facilmente. Por exemplo, pesquisar por "frasco" e "frascos" resultará na mesma pesquisa porque eles são basicamente a mesma coisa.
  2. SearchQuery- traduz as palavras fornecidas a nós como uma consulta do formulário, passa-as por um algoritmo de derivação e, em seguida, procura correspondências para todos os termos resultantes.
  3. SearchRank- nos permite ordenar os resultados por relevância. Ele leva em consideração a frequência com que os termos de consulta aparecem no documento, quão próximos os termos estão no documento e quão importante é a parte do documento onde eles ocorrem.

Adicione as importações:

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank

Página de pesquisa

Compare os resultados da pesquisa básica com os da pesquisa de texto completo. Há uma clara diferença. Na pesquisa de texto completo, a consulta com os resultados mais altos é mostrada primeiro. Este é o poder de SearchRank. Combinar SearchVector, SearchQuery, e SearchRanké uma maneira rápida de produzir uma pesquisa muito mais poderosa e precisa do que a pesquisa básica.

Adicionando Pesos

A pesquisa de texto completo nos dá a capacidade de adicionar mais importância a alguns campos em nossa tabela no banco de dados em relação a outros campos. Podemos conseguir isso adicionando pesos às nossas consultas.

O peso deve ser uma das seguintes letras D, C, B, A. Por padrão, esses pesos referem-se aos números 0,1, 0,2, 0,4 e 1,0, respectivamente.

Atualização SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", weight="B") + SearchVector(
            "quote", weight="A"
        )
        search_query = SearchQuery(query)
        return (
            Quote.objects.annotate(rank=SearchRank(search_vector, search_query))
            .filter(rank__gte=0.3)
            .order_by("-rank")
        )

Aqui, você adicionou pesos ao SearchVectorusando os campos namee . quotePesos de 0,4 e 1,0 foram aplicados aos campos de nome e cotação, respectivamente. Portanto, as correspondências de cotação prevalecerão sobre as correspondências de conteúdo de nome. Por fim, você filtrou os resultados para exibir apenas os maiores que 0,3.

Adicionando uma visualização aos resultados da pesquisa

Nesta seção, você adicionará uma pequena visualização do resultado da pesquisa por meio do método SearchHeadline . Isso destacará a consulta do resultado da pesquisa.

Atualize SearchResultsListnovamente:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", "quote")
        search_query = SearchQuery(query)
        search_headline = SearchHeadline("quote", search_query)
        return Quote.objects.annotate(
            search=search_vector,
            rank=SearchRank(search_vector, search_query)
        ).annotate(headline=search_headline).filter(search=search_query).order_by("-rank")

As SearchHeadlinetomadas no campo que você deseja visualizar. Nesse caso, este será o quotecampo junto com a consulta, que estará em negrito.

Certifique-se de adicionar a importação:

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank, SearchHeadline

Antes de tentar algumas pesquisas, atualize o <li></li>in quotes/templates/search.html da seguinte forma:

<li>{{ quote.headline | safe }} - <b>By <i>{{ quote.name }}</i></b></li>

Agora, em vez de mostrar as cotações como você fez antes, apenas uma visualização do campo de cotação completo é exibida junto com a consulta de pesquisa destacada.

Melhorando o desempenho

A pesquisa de texto completo é um processo intensivo. Para combater o desempenho lento, você pode:

  1. Salve os vetores de pesquisa no banco de dados com SearchVectorField . Em outras palavras, em vez de converter as strings em vetores de pesquisa dinamicamente, criaremos um campo de banco de dados separado que contém os vetores de pesquisa processados ​​e atualizaremos o campo sempre que houver uma inserção ou atualização nos campos quoteou .name
  2. Crie um índice de banco de dados , que é uma estrutura de dados que aumenta a velocidade dos processos de recuperação de dados em um banco de dados. Portanto, agiliza a consulta. O Postgres oferece vários índices para trabalhar que podem ser aplicáveis ​​a diferentes situações. O GinIndex é sem dúvida o mais popular.

Para saber mais sobre desempenho com pesquisa de texto completo, revise a seção Desempenho dos documentos do Django.

Campo de vetor de pesquisa

Comece adicionando um novo campo SearchVectorField ao Quotemodelo em quotes/models.py :

from django.contrib.postgres.search import SearchVectorField  # new
from django.db import models


class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)
    search_vector = SearchVectorField(null=True)  # new

    def __str__(self):
        return self.quote

Crie o arquivo de migração:

$ docker-compose exec web python manage.py makemigrations

Agora, você só poderá preencher este campo quando os objetos quoteou já existirem no banco de dados. nameAssim, precisamos adicionar um gatilho para atualizar o search_vectorcampo sempre que os campos quoteou nameforem atualizados. Para conseguir isso, crie um arquivo de migração personalizado em "quotes/migrations" chamado 0003_search_vector_trigger.py :

from django.contrib.postgres.search import SearchVector
from django.db import migrations


def compute_search_vector(apps, schema_editor):
    Quote = apps.get_model("quotes", "Quote")
    Quote.objects.update(search_vector=SearchVector("name", "quote"))


class Migration(migrations.Migration):

    dependencies = [
        ("quotes", "0002_quote_search_vector"),
    ]

    operations = [
        migrations.RunSQL(
            sql="""
            CREATE TRIGGER search_vector_trigger
            BEFORE INSERT OR UPDATE OF name, quote, search_vector
            ON quotes_quote
            FOR EACH ROW EXECUTE PROCEDURE
            tsvector_update_trigger(
                search_vector, 'pg_catalog.english', name, quote
            );
            UPDATE quotes_quote SET search_vector = NULL;
            """,
            reverse_sql="""
            DROP TRIGGER IF EXISTS search_vector_trigger
            ON quotes_quote;
            """,
        ),
        migrations.RunPython(
            compute_search_vector, reverse_code=migrations.RunPython.noop
        ),
    ]

Dependendo da estrutura do seu projeto, pode ser necessário atualizar o nome do arquivo de migração anterior no formato dependencies.

Aplique as migrações:

$ docker-compose exec web python manage.py migrate

Para usar o novo campo para pesquisas, atualize SearchResultsListassim:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(search_vector=query)

Atualize <li></li>entre aspas/templates/search.html novamente:

<li>{{ quote.quote | safe }} - <b>By <i>{{ quote.name }}</i></b></li>

Índice

Por fim, vamos configurar um índice funcional, GinIndex .

Atualize o Quotemodelo:

from django.contrib.postgres.indexes import GinIndex  # new
from django.contrib.postgres.search import SearchVectorField
from django.db import models


class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)
    search_vector = SearchVectorField(null=True)

    def __str__(self):
        return self.quote

    # new
    class Meta:
        indexes = [
            GinIndex(fields=["search_vector"]),
        ]

Crie e aplique as migrações uma última vez:

$ docker-compose exec web python manage.py makemigrations
$ docker-compose exec web python manage.py migrate

Teste-o.

Conclusão

Neste tutorial, você foi guiado pela adição de pesquisa básica e de texto completo a um aplicativo Django. Também analisamos como otimizar a funcionalidade de pesquisa de texto completo adicionando um campo de vetor de pesquisa e um índice de banco de dados.

Pegue o código completo do repositório django-search .

Fonte:  https://testdrive.io

#django #postgre 

What is GEEK

Buddha Community

Pesquisa Básica E De Texto Completo Com Django E Postgres
Ahebwe  Oscar

Ahebwe Oscar

1620177818

Django admin full Customization step by step

Welcome to my blog , hey everyone in this article you learn how to customize the Django app and view in the article you will know how to register  and unregister  models from the admin view how to add filtering how to add a custom input field, and a button that triggers an action on all objects and even how to change the look of your app and page using the Django suit package let’s get started.

Database

Custom Titles of Django Admin

Exclude in Django Admin

Fields in Django Admin

#django #create super user django #customize django admin dashboard #django admin #django admin custom field display #django admin customization #django admin full customization #django admin interface #django admin register all models #django customization

Neil  Morgan

Neil Morgan

1660498920

Pesquisa Básica E De Texto Completo Com Django E Postgres

Ao contrário dos bancos de dados relacionais, a pesquisa de texto completo não é padronizada. Existem várias opções de código aberto, como ElasticSearch, Solr e Xapian. O ElasticSearch é provavelmente a solução mais popular; no entanto, é complicado de configurar e manter. Além disso, se você não estiver aproveitando alguns dos recursos avançados que o ElasticSearch oferece, você deve ficar com os recursos de pesquisa de texto completo que muitos bancos de dados relacionais (como Postgres, MySQL, SQLite) e não relacionais (como MongoDB e CouchDB ) oferta. O Postgres, em particular, é adequado para pesquisa de texto completo. O Django também oferece suporte pronto para uso.

Para a grande maioria de seus aplicativos Django, você deve, no mínimo, começar aproveitando a pesquisa de texto completo do Postgres antes de procurar uma solução mais poderosa como ElasticSearch ou Solr.

Neste tutorial, você aprenderá como adicionar pesquisa básica e de texto completo a um aplicativo Django com o Postgres. Você também otimizará a pesquisa de texto completo adicionando um campo de vetor de pesquisa e um índice de banco de dados.

Objetivos

Ao final deste tutorial, você será capaz de:

  1. Configure a funcionalidade de pesquisa básica em um aplicativo Django com o módulo de objeto Q
  2. Adicionar pesquisa de texto completo a um aplicativo Django
  3. Classifique os resultados da pesquisa de texto completo por relevância usando técnicas de lematização, classificação e ponderação
  4. Adicione uma visualização aos seus resultados de pesquisa
  5. Otimize a pesquisa de texto completo com um campo de vetor de pesquisa e um índice de banco de dados

Configuração e visão geral do projeto

Clone o branch base do repositório django-search :

$ git clone https://github.com/testdrivenio/django-search --branch base --single-branch
$ cd django-search

Você usará o Docker para simplificar a configuração e execução do Postgres junto com o Django.

Na raiz do projeto, crie as imagens e ative os contêineres do Docker:

$ docker-compose up -d --build

Em seguida, aplique as migrações e crie um superusuário:

$ docker-compose exec web python manage.py makemigrations
$ docker-compose exec web python manage.py migrate
$ docker-compose exec web python manage.py createsuperuser

Depois de concluído, navegue até http://127.0.0.1:8011/quotes/ para garantir que o aplicativo funcione conforme o esperado. Você deve ver o seguinte:

Página inicial de cotação

Quer aprender a trabalhar com Django e Postgres? Confira o artigo Dockerizing Django com Postgres, Gunicorn e Nginx .

Anote o Quotemodelo em quotes/models.py :

from django.db import models

class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)

    def __str__(self):
        return self.quote

Em seguida, execute o seguinte comando de gerenciamento para adicionar 10.000 cotações ao banco de dados:

$ docker-compose exec web python manage.py add_quotes

Isso levará alguns minutos. Uma vez feito, navegue até http://127.0.0.1:8011/quotes/ para ver os dados.

A saída da visualização é armazenada em cache por cinco minutos, portanto, você pode comentar @method_decoratorem quotes/views.py para carregar as aspas. Certifique-se de remover o comentário uma vez feito.

Página inicial de cotação

No arquivo quotes/templates/quote.html , você tem um formulário básico com um campo de entrada de pesquisa:

<form action="{% url 'search_results' %}" method="get">
  <input
    type="search"
    name="q"
    placeholder="Search by name or quote..."
    class="form-control"
  />
</form>

Ao enviar, o formulário envia os dados para o back-end. Uma GETsolicitação é usada em vez de uma POSTpara que tenhamos acesso à string de consulta tanto na URL quanto na visualização do Django, permitindo que os usuários compartilhem os resultados da pesquisa como links.

Antes de prosseguir, dê uma olhada rápida na estrutura do projeto e no restante do código.

Pesquisa básica

Quando se trata de pesquisa, com o Django, você normalmente começará realizando consultas de pesquisa com containsou icontainspara correspondências exatas. O objeto Q também pode ser usado para adicionar operadores lógicos AND ( &) ou OR ( ).|

Por exemplo, usando o operador OR, substitua o SearchResultsListpadrão de 's QuerySetem quotes/views.py assim:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(
            Q(name__icontains=query) | Q(quote__icontains=query)
        )

Aqui, usamos o método de filtro para filtrar os campos ou name. quoteAlém disso, também usamos a extensão icontains para verificar se a consulta está presente nos campos nameou quote(não diferencia maiúsculas de minúsculas). Um resultado positivo será retornado se uma correspondência for encontrada.

Não esqueça da importação:

from django.db.models import Q

Experimente:

Página de pesquisa

Para conjuntos de dados pequenos, essa é uma ótima maneira de adicionar funcionalidades básicas de pesquisa ao seu aplicativo. Se você estiver lidando com um grande conjunto de dados ou quiser uma funcionalidade de pesquisa que pareça um mecanismo de pesquisa da Internet, convém mudar para a pesquisa de texto completo.

Pesquisa de texto completo

A pesquisa básica que vimos anteriormente tem várias limitações, especialmente quando você deseja realizar pesquisas complexas.

Como mencionado, com a pesquisa básica, você só pode realizar correspondências exatas.

Outra limitação é a das palavras de parada . Palavras de parada são palavras como "a", "an" e "the". Essas palavras são comuns e pouco significativas, portanto, devem ser ignoradas. Para testar, tente pesquisar uma palavra com "the" na frente. Digamos que você pesquisou por "no meio". Nesse caso, você verá apenas resultados para "o meio", portanto não verá resultados que tenham a palavra "meio" sem "o" antes dela.

Digamos que você tenha essas duas frases:

  1. Eu estou no meio.
  2. Você não gosta do ensino médio.

Você obterá o seguinte retorno com cada tipo de pesquisa:

ConsultaPesquisa básicaPesquisa de texto completo
"o meio"primeiro1 e 2
"meio"1 e 21 e 2

Outra questão é a de ignorar palavras semelhantes. Com a pesquisa básica, apenas as correspondências exatas são retornadas. No entanto, com a pesquisa de texto completo, palavras semelhantes são contabilizadas. Para testar, tente encontrar algumas palavras semelhantes como "pônei" e "pôneis". Com a pesquisa básica, se você pesquisar por "pônei", não verá resultados que contenham "pôneis" - e vice-versa.

Digamos que você tenha essas duas frases.

  1. Eu sou um pônei.
  2. Você não gosta de pôneis

Você obterá o seguinte retorno com cada tipo de pesquisa:

ConsultaPesquisa básicaPesquisa de texto completo
"pónei"primeiro1 e 2
"pôneis"21 e 2

Com a pesquisa de texto completo, esses dois problemas são atenuados. No entanto, lembre-se de que, dependendo do seu objetivo, a pesquisa de texto completo pode diminuir a precisão (qualidade) e a recuperação (quantidade de resultados relevantes). Normalmente, a pesquisa de texto completo é menos precisa do que a pesquisa básica, pois a pesquisa básica produz correspondências exatas. Dito isso, se você estiver pesquisando em grandes conjuntos de dados com grandes blocos de texto, a pesquisa de texto completo é preferível, pois geralmente é muito mais rápida.

A pesquisa de texto completo é uma técnica de pesquisa avançada que examina todas as palavras em cada documento armazenado enquanto tenta corresponder aos critérios de pesquisa. Além disso, com a pesquisa de texto completo, você pode empregar derivação específica do idioma nas palavras que estão sendo indexadas. Por exemplo, as palavras "drives", "drive" e "driven" serão registradas sob a palavra de conceito único "drive". Stemming é o processo de reduzir palavras à sua raiz, base ou forma de raiz.

Basta dizer que a pesquisa de texto completo não é perfeita. É provável que recupere muitos documentos que não são relevantes (falsos positivos) para a consulta de pesquisa pretendida. No entanto, existem algumas técnicas baseadas em algoritmos Bayesianos que podem ajudar a reduzir tais problemas.

Para aproveitar a pesquisa de texto completo do Postgres com o Django, adicione django.contrib.postgresà sua INSTALLED_APPSlista:

INSTALLED_APPS = [
    ...

    "django.contrib.postgres",  # new
]

Em seguida, vamos ver dois exemplos rápidos de pesquisa de texto completo, em um único campo e em vários campos.

Pesquisa de campo único

Atualize a get_querysetfunção na função de SearchResultsListvisualização da seguinte forma:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(quote__search=query)

Aqui, configuramos a pesquisa de texto completo em um único campo -- o campo de cotação.

Página de pesquisa

Como você pode ver, leva em consideração palavras semelhantes. No exemplo acima, "pôneis" e "pônei" são tratados como palavras semelhantes.

Pesquisa de vários campos

Para pesquisar em vários campos e em modelos relacionados, você pode usar a SearchVectorclasse.

Novamente, atualize SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.annotate(search=SearchVector("name", "quote")).filter(
            search=query
        )

Para pesquisar em vários campos, você anota o conjunto de consultas usando um SearchVector. O vetor são os dados que você está procurando, que foram convertidos em um formulário fácil de pesquisar. No exemplo acima, esses dados são os campos namee em seu banco de dados.quote

Certifique-se de adicionar a importação:

from django.contrib.postgres.search import SearchVector

Tente algumas pesquisas.

Derivação e classificação

Nesta seção, você combinará vários métodos, como SearchVector , SearchQuery e SearchRank para produzir uma pesquisa muito robusta que usa lematização e classificação.

Novamente, stemming é o processo de reduzir palavras ao seu radical, base ou raiz. Com a derivação, palavras como "criança" e "crianças" serão tratadas como palavras semelhantes. O ranking, por outro lado, nos permite ordenar os resultados por relevância.

Atualização SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", "quote")
        search_query = SearchQuery(query)
        return (
            Quote.objects.annotate(
                search=search_vector, rank=SearchRank(search_vector, search_query)
            )
            .filter(search=search_query)
            .order_by("-rank")
        )

O que está acontecendo aqui?

  1. SearchVector- novamente você usou um vetor de pesquisa para pesquisar em vários campos. Os dados são convertidos em outro formulário, pois você não está mais apenas pesquisando o texto bruto como fazia quando icontainsera usado. Portanto, com isso, você poderá pesquisar plurais facilmente. Por exemplo, pesquisar por "frasco" e "frascos" resultará na mesma pesquisa porque eles são basicamente a mesma coisa.
  2. SearchQuery- traduz as palavras fornecidas a nós como uma consulta do formulário, passa-as por um algoritmo de derivação e, em seguida, procura correspondências para todos os termos resultantes.
  3. SearchRank- nos permite ordenar os resultados por relevância. Ele leva em consideração a frequência com que os termos de consulta aparecem no documento, quão próximos os termos estão no documento e quão importante é a parte do documento onde eles ocorrem.

Adicione as importações:

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank

Página de pesquisa

Compare os resultados da pesquisa básica com os da pesquisa de texto completo. Há uma clara diferença. Na pesquisa de texto completo, a consulta com os resultados mais altos é mostrada primeiro. Este é o poder de SearchRank. Combinar SearchVector, SearchQuery, e SearchRanké uma maneira rápida de produzir uma pesquisa muito mais poderosa e precisa do que a pesquisa básica.

Adicionando Pesos

A pesquisa de texto completo nos dá a capacidade de adicionar mais importância a alguns campos em nossa tabela no banco de dados em relação a outros campos. Podemos conseguir isso adicionando pesos às nossas consultas.

O peso deve ser uma das seguintes letras D, C, B, A. Por padrão, esses pesos referem-se aos números 0,1, 0,2, 0,4 e 1,0, respectivamente.

Atualização SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", weight="B") + SearchVector(
            "quote", weight="A"
        )
        search_query = SearchQuery(query)
        return (
            Quote.objects.annotate(rank=SearchRank(search_vector, search_query))
            .filter(rank__gte=0.3)
            .order_by("-rank")
        )

Aqui, você adicionou pesos ao SearchVectorusando os campos namee . quotePesos de 0,4 e 1,0 foram aplicados aos campos de nome e cotação, respectivamente. Portanto, as correspondências de cotação prevalecerão sobre as correspondências de conteúdo de nome. Por fim, você filtrou os resultados para exibir apenas os maiores que 0,3.

Adicionando uma visualização aos resultados da pesquisa

Nesta seção, você adicionará uma pequena visualização do resultado da pesquisa por meio do método SearchHeadline . Isso destacará a consulta do resultado da pesquisa.

Atualize SearchResultsListnovamente:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", "quote")
        search_query = SearchQuery(query)
        search_headline = SearchHeadline("quote", search_query)
        return Quote.objects.annotate(
            search=search_vector,
            rank=SearchRank(search_vector, search_query)
        ).annotate(headline=search_headline).filter(search=search_query).order_by("-rank")

As SearchHeadlinetomadas no campo que você deseja visualizar. Nesse caso, este será o quotecampo junto com a consulta, que estará em negrito.

Certifique-se de adicionar a importação:

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank, SearchHeadline

Antes de tentar algumas pesquisas, atualize o <li></li>in quotes/templates/search.html da seguinte forma:

<li>{{ quote.headline | safe }} - <b>By <i>{{ quote.name }}</i></b></li>

Agora, em vez de mostrar as cotações como você fez antes, apenas uma visualização do campo de cotação completo é exibida junto com a consulta de pesquisa destacada.

Melhorando o desempenho

A pesquisa de texto completo é um processo intensivo. Para combater o desempenho lento, você pode:

  1. Salve os vetores de pesquisa no banco de dados com SearchVectorField . Em outras palavras, em vez de converter as strings em vetores de pesquisa dinamicamente, criaremos um campo de banco de dados separado que contém os vetores de pesquisa processados ​​e atualizaremos o campo sempre que houver uma inserção ou atualização nos campos quoteou .name
  2. Crie um índice de banco de dados , que é uma estrutura de dados que aumenta a velocidade dos processos de recuperação de dados em um banco de dados. Portanto, agiliza a consulta. O Postgres oferece vários índices para trabalhar que podem ser aplicáveis ​​a diferentes situações. O GinIndex é sem dúvida o mais popular.

Para saber mais sobre desempenho com pesquisa de texto completo, revise a seção Desempenho dos documentos do Django.

Campo de vetor de pesquisa

Comece adicionando um novo campo SearchVectorField ao Quotemodelo em quotes/models.py :

from django.contrib.postgres.search import SearchVectorField  # new
from django.db import models


class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)
    search_vector = SearchVectorField(null=True)  # new

    def __str__(self):
        return self.quote

Crie o arquivo de migração:

$ docker-compose exec web python manage.py makemigrations

Agora, você só poderá preencher este campo quando os objetos quoteou já existirem no banco de dados. nameAssim, precisamos adicionar um gatilho para atualizar o search_vectorcampo sempre que os campos quoteou nameforem atualizados. Para conseguir isso, crie um arquivo de migração personalizado em "quotes/migrations" chamado 0003_search_vector_trigger.py :

from django.contrib.postgres.search import SearchVector
from django.db import migrations


def compute_search_vector(apps, schema_editor):
    Quote = apps.get_model("quotes", "Quote")
    Quote.objects.update(search_vector=SearchVector("name", "quote"))


class Migration(migrations.Migration):

    dependencies = [
        ("quotes", "0002_quote_search_vector"),
    ]

    operations = [
        migrations.RunSQL(
            sql="""
            CREATE TRIGGER search_vector_trigger
            BEFORE INSERT OR UPDATE OF name, quote, search_vector
            ON quotes_quote
            FOR EACH ROW EXECUTE PROCEDURE
            tsvector_update_trigger(
                search_vector, 'pg_catalog.english', name, quote
            );
            UPDATE quotes_quote SET search_vector = NULL;
            """,
            reverse_sql="""
            DROP TRIGGER IF EXISTS search_vector_trigger
            ON quotes_quote;
            """,
        ),
        migrations.RunPython(
            compute_search_vector, reverse_code=migrations.RunPython.noop
        ),
    ]

Dependendo da estrutura do seu projeto, pode ser necessário atualizar o nome do arquivo de migração anterior no formato dependencies.

Aplique as migrações:

$ docker-compose exec web python manage.py migrate

Para usar o novo campo para pesquisas, atualize SearchResultsListassim:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(search_vector=query)

Atualize <li></li>entre aspas/templates/search.html novamente:

<li>{{ quote.quote | safe }} - <b>By <i>{{ quote.name }}</i></b></li>

Índice

Por fim, vamos configurar um índice funcional, GinIndex .

Atualize o Quotemodelo:

from django.contrib.postgres.indexes import GinIndex  # new
from django.contrib.postgres.search import SearchVectorField
from django.db import models


class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)
    search_vector = SearchVectorField(null=True)

    def __str__(self):
        return self.quote

    # new
    class Meta:
        indexes = [
            GinIndex(fields=["search_vector"]),
        ]

Crie e aplique as migrações uma última vez:

$ docker-compose exec web python manage.py makemigrations
$ docker-compose exec web python manage.py migrate

Teste-o.

Conclusão

Neste tutorial, você foi guiado pela adição de pesquisa básica e de texto completo a um aplicativo Django. Também analisamos como otimizar a funcionalidade de pesquisa de texto completo adicionando um campo de vetor de pesquisa e um índice de banco de dados.

Pegue o código completo do repositório django-search .

Fonte:  https://testdrive.io

#django #postgre 

Ahebwe  Oscar

Ahebwe Oscar

1620185280

How model queries work in Django

How model queries work in Django

Welcome to my blog, hey everyone in this article we are going to be working with queries in Django so for any web app that you build your going to want to write a query so you can retrieve information from your database so in this article I’ll be showing you all the different ways that you can write queries and it should cover about 90% of the cases that you’ll have when you’re writing your code the other 10% depend on your specific use case you may have to get more complicated but for the most part what I cover in this article should be able to help you so let’s start with the model that I have I’ve already created it.

**Read More : **How to make Chatbot in Python.

Read More : Django Admin Full Customization step by step

let’s just get into this diagram that I made so in here:

django queries aboutDescribe each parameter in Django querset

we’re making a simple query for the myModel table so we want to pull out all the information in the database so we have this variable which is gonna hold a return value and we have our myModel models so this is simply the myModel model name so whatever you named your model just make sure you specify that and we’re gonna access the objects attribute once we get that object’s attribute we can simply use the all method and this will return all the information in the database so we’re gonna start with all and then we will go into getting single items filtering that data and go to our command prompt.

Here and we’ll actually start making our queries from here to do this let’s just go ahead and run** Python manage.py shell** and I am in my project file so make sure you’re in there when you start and what this does is it gives us an interactive shell to actually start working with our data so this is a lot like the Python shell but because we did manage.py it allows us to do things a Django way and actually query our database now open up the command prompt and let’s go ahead and start making our first queries.

#django #django model queries #django orm #django queries #django query #model django query #model query #query with django

Búsqueda Básica Y De Texto Completo Con Django Y Postgres

A diferencia de las bases de datos relacionales, la búsqueda de texto completo no está estandarizada. Hay varias opciones de código abierto como ElasticSearch, Solr y Xapian. ElasticSearch es probablemente la solución más popular; sin embargo, es complicado de configurar y mantener. Además, si no está aprovechando algunas de las características avanzadas que ofrece ElasticSearch, debe ceñirse a las capacidades de búsqueda de texto completo que muchas bases de datos relacionales (como Postgres, MySQL, SQLite) y no relacionales (como MongoDB y CouchDB). ) oferta. Postgres en particular es muy adecuado para la búsqueda de texto completo. Django también lo admite listo para usar.

Para la gran mayoría de sus aplicaciones de Django, debe, como mínimo, comenzar aprovechando la búsqueda de texto completo de Postgres antes de buscar una solución más poderosa como ElasticSearch o Solr.

En este tutorial, aprenderá a agregar búsquedas básicas y de texto completo a una aplicación de Django con Postgres. También optimizará la búsqueda de texto completo agregando un campo de vector de búsqueda y un índice de base de datos.

Objetivos

Al final de este tutorial, podrá:

  1. Configure la funcionalidad de búsqueda básica en una aplicación Django con el módulo de objetos Q
  2. Agregar búsqueda de texto completo a una aplicación Django
  3. Ordene los resultados de búsqueda de texto completo por relevancia utilizando técnicas de derivación, clasificación y ponderación
  4. Agrega una vista previa a tus resultados de búsqueda
  5. Optimice la búsqueda de texto completo con un campo de vector de búsqueda y un índice de base de datos

Configuración y descripción general del proyecto

Clona la rama base del repositorio django-search :

$ git clone https://github.com/testdrivenio/django-search --branch base --single-branch
$ cd django-search

Utilizará Docker para simplificar la configuración y ejecución de Postgres junto con Django.

Desde la raíz del proyecto, cree las imágenes y active los contenedores de Docker:

$ docker-compose up -d --build

A continuación, aplique las migraciones y cree un superusuario:

$ docker-compose exec web python manage.py makemigrations
$ docker-compose exec web python manage.py migrate
$ docker-compose exec web python manage.py createsuperuser

Una vez hecho esto, vaya a http://127.0.0.1:8011/quotes/ para asegurarse de que la aplicación funcione como se espera. Deberías ver lo siguiente:

Cotizar página de inicio

¿Quieres aprender a trabajar con Django y Postgres? Consulte el artículo Dockerizing Django with Postgres, Gunicorn y Nginx .

Toma nota del Quotemodelo en quotes/models.py :

from django.db import models

class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)

    def __str__(self):
        return self.quote

A continuación, ejecute el siguiente comando de administración para agregar 10 000 cotizaciones a la base de datos:

$ docker-compose exec web python manage.py add_quotes

Esto tomará un par de minutos. Una vez hecho esto, navegue a http://127.0.0.1:8011/quotes/ para ver los datos.

El resultado de la vista se almacena en caché durante cinco minutos, por lo que es posible que desee comentar @method_decoratoren quotes/views.py para cargar las comillas. Asegúrate de eliminar el comentario una vez hecho.

Cotizar página de inicio

En el archivo quotes/templates/quote.html , tiene un formulario básico con un campo de entrada de búsqueda:

<form action="{% url 'search_results' %}" method="get">
  <input
    type="search"
    name="q"
    placeholder="Search by name or quote..."
    class="form-control"
  />
</form>

Al enviar, el formulario envía los datos al backend. Se GETusa una solicitud en lugar de una POSTpara que tengamos acceso a la cadena de consulta tanto en la URL como en la vista de Django, lo que permite a los usuarios compartir los resultados de la búsqueda como enlaces.

Antes de continuar, eche un vistazo rápido a la estructura del proyecto y al resto del código.

Búsqueda básica

Cuando se trata de buscar, con Django, normalmente comenzará realizando consultas de búsqueda con containso icontainspara coincidencias exactas. El objeto Q también se puede usar para agregar operadores lógicos AND ( &) u OR ( ).|

Por ejemplo, usando el operador OR, invalide el SearchResultsListvalor predeterminado QuerySeten quotes/views.py así:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(
            Q(name__icontains=query) | Q(quote__icontains=query)
        )

Aquí, usamos el método de filtro para filtrar contra los campos nameo . quoteAdemás, también usamos la extensión icontains para verificar si la consulta está presente en los campos nameo quote(sin distinción entre mayúsculas y minúsculas). Se devolverá un resultado positivo si se encuentra una coincidencia.

No olvides la importación:

from django.db.models import Q

Pruébalo:

Página de búsqueda

Para conjuntos de datos pequeños, esta es una excelente manera de agregar funciones de búsqueda básicas a su aplicación. Si está tratando con un gran conjunto de datos o desea una funcionalidad de búsqueda que se sienta como un motor de búsqueda de Internet, querrá pasar a la búsqueda de texto completo.

Búsqueda de texto completo

La búsqueda básica que vimos anteriormente tiene varias limitaciones, especialmente cuando desea realizar búsquedas complejas.

Como se mencionó, con la búsqueda básica, solo puede realizar coincidencias exactas.

Otra limitación es la de las palabras vacías . Las palabras vacías son palabras como "a", "an" y "the". Estas palabras son comunes e insuficientemente significativas, por lo que deben ignorarse. Para probar, intente buscar una palabra con "el" delante de ella. Digamos que buscaste "el medio". En este caso, solo verá resultados para "el medio", por lo que no verá ningún resultado que tenga la palabra "medio" sin "el" antes.

Digamos que tienes estas dos oraciones:

  1. Estoy en el medio.
  2. No te gusta la secundaria.

Obtendrá lo siguiente con cada tipo de búsqueda:

ConsultaBúsqueda básicaBúsqueda de texto completo
"la mitad"primero1 y 2
"medio"1 y 21 y 2

Otro problema es el de ignorar palabras similares. Con la búsqueda básica, solo se devuelven coincidencias exactas. Sin embargo, con la búsqueda de texto completo, se tienen en cuenta palabras similares. Para probar, trata de encontrar algunas palabras similares como "pony" y "ponis". Con la búsqueda básica, si buscas "pony", no verás resultados que contengan "ponis", y viceversa.

Digamos que tienes estas dos oraciones.

  1. soy un pony
  2. no te gustan los ponis

Obtendrá lo siguiente con cada tipo de búsqueda:

ConsultaBúsqueda básicaBúsqueda de texto completo
"poni"primero1 y 2
"ponis"21 y 2

Con la búsqueda de texto completo, ambos problemas se mitigan. Sin embargo, tenga en cuenta que, según su objetivo, la búsqueda de texto completo puede disminuir la precisión (calidad) y la recuperación (cantidad de resultados relevantes). Por lo general, la búsqueda de texto completo es menos precisa que la búsqueda básica, ya que la búsqueda básica produce coincidencias exactas. Dicho esto, si está buscando en grandes conjuntos de datos con grandes bloques de texto, se prefiere la búsqueda de texto completo, ya que suele ser mucho más rápida.

La búsqueda de texto completo es una técnica de búsqueda avanzada que examina todas las palabras en cada documento almacenado mientras intenta coincidir con los criterios de búsqueda. Además, con la búsqueda de texto completo, puede emplear derivaciones específicas del idioma en las palabras que se indexan. Por ejemplo, la palabra "drives", "driven" y "driven" se registrarán bajo la palabra de concepto único "drive". Stemming es el proceso de reducir las palabras a su raíz, base o forma de raíz.

Baste decir que la búsqueda de texto completo no es perfecta. Es probable que recupere muchos documentos que no son relevantes (falsos positivos) para la consulta de búsqueda prevista. Sin embargo, existen algunas técnicas basadas en algoritmos bayesianos que pueden ayudar a reducir este tipo de problemas.

To take advantage of Postgres full-text search with Django, add django.contrib.postgres to your INSTALLED_APPS list:

INSTALLED_APPS = [
    ...

    "django.contrib.postgres",  # new
]

Next, let's look at two quick examples of full-text search, on a single field and on multiple fields.

Single Field Search

Update the get_queryset function under the SearchResultsList view function like so:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(quote__search=query)

Here, we set up full-text search against a single field -- the quote field.

Página de búsqueda

As you can see, it takes similar words into account. In the above example, "ponies" and "pony" are treated as similar words.

Multi Field Search

To search against multiple fields and on related models, you can use the SearchVector class.

Again, update SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.annotate(search=SearchVector("name", "quote")).filter(
            search=query
        )

Para buscar en varios campos, anote el conjunto de consulta con un archivo SearchVector. El vector son los datos que está buscando, que se han convertido en un formulario que es fácil de buscar. En el ejemplo anterior, estos datos son los campos namey en su base de datos.quote

Asegúrate de agregar la importación:

from django.contrib.postgres.search import SearchVector

Pruebe algunas búsquedas.

Derivación y Clasificación

En esta sección, combinará varios métodos, como SearchVector , SearchQuery y SearchRank , para producir una búsqueda muy sólida que utiliza derivación y clasificación.

Una vez más, la derivación es el proceso de reducir las palabras a su raíz, base o forma de raíz. Con la lematización, palabras como "niño" y "niños" se tratarán como palabras similares. La clasificación, por otro lado, nos permite ordenar los resultados por relevancia.

Actualizar SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", "quote")
        search_query = SearchQuery(query)
        return (
            Quote.objects.annotate(
                search=search_vector, rank=SearchRank(search_vector, search_query)
            )
            .filter(search=search_query)
            .order_by("-rank")
        )

¿Que esta pasando aqui?

  1. SearchVector- nuevamente usó un vector de búsqueda para buscar en múltiples campos. Los datos se convierten en otra forma, ya que ya no solo está buscando el texto sin procesar como lo hizo cuando icontainsse utilizó. Por lo tanto, con esto, podrás buscar plurales fácilmente. Por ejemplo, buscar "frasco" y "frascos" dará como resultado la misma búsqueda porque son, bueno, básicamente lo mismo.
  2. SearchQuery - translates the words provided to us as a query from the form, passes them through a stemming algorithm, and then it looks for matches for all of the resulting terms.
  3. SearchRank - allows us to order the results by relevancy. It takes into account how often the query terms appear in the document, how close the terms are on the document, and how important the part of the document is where they occur.

Add the imports:

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank

Página de búsqueda

Compare the results from the basic search to that of the full-text search. There's a clear difference. In the full-text search, the query with the highest results is shown first. This is the power of SearchRank. Combining SearchVector, SearchQuery, and SearchRank is a quick way to produce a much more powerful and precise search than the basic search.

Adding Weights

La búsqueda de texto completo nos brinda la capacidad de agregar más importancia a algunos campos en nuestra tabla en la base de datos sobre otros campos. Podemos lograr esto agregando pesos a nuestras consultas.

El peso debe ser una de las siguientes letras D, C, B, A. De forma predeterminada, estos pesos se refieren a los números 0.1, 0.2, 0.4 y 1.0, respectivamente.

Actualizar SearchResultsList:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", weight="B") + SearchVector(
            "quote", weight="A"
        )
        search_query = SearchQuery(query)
        return (
            Quote.objects.annotate(rank=SearchRank(search_vector, search_query))
            .filter(rank__gte=0.3)
            .order_by("-rank")
        )

Aquí, agregó pesos al SearchVectoruso de los campos namey . quoteSe aplicaron pesos de 0,4 y 1,0 a los campos de nombre y cita, respectivamente. Por lo tanto, las coincidencias de citas prevalecerán sobre las coincidencias de contenido de nombres. Finalmente, filtró los resultados para mostrar solo los que son mayores que 0.3.

Adición de una vista previa a los resultados de búsqueda

En esta sección, agregará una pequeña vista previa de su resultado de búsqueda a través del método SearchHeadline . Esto resaltará la consulta de resultados de búsqueda.

Actualizar de SearchResultsListnuevo:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        search_vector = SearchVector("name", "quote")
        search_query = SearchQuery(query)
        search_headline = SearchHeadline("quote", search_query)
        return Quote.objects.annotate(
            search=search_vector,
            rank=SearchRank(search_vector, search_query)
        ).annotate(headline=search_headline).filter(search=search_query).order_by("-rank")

Las SearchHeadlinetomas en el campo que desea obtener una vista previa. En este caso, este será el quotecampo junto con la consulta, que estará en negrita.

Asegúrate de agregar la importación:

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank, SearchHeadline

Antes de probar algunas búsquedas, actualice <li></li>en quotes/templates/search.html así:

<li>{{ quote.headline | safe }} - <b>By <i>{{ quote.name }}</i></b></li>

Ahora, en lugar de mostrar las cotizaciones como lo hacía antes, solo se muestra una vista previa del campo de cotización completo junto con la consulta de búsqueda resaltada.

Impulsar el rendimiento

La búsqueda de texto completo es un proceso intensivo. Para combatir el rendimiento lento, puede:

  1. Save the search vectors to the database with SearchVectorField. In other words, rather than converting the strings to search vectors on the fly, we'll create a separate database field that contains the processed search vectors and update the field any time there's an insert or update to either the quote or name fields.
  2. Create a database index, which is a data structure that enhances the speed of the data retrieval processes on a database. It, therefore, speeds up the query. Postgres gives you several indexes to work with that might be applicable for different situations. The GinIndex is arguably the most popular.

Para obtener más información sobre el rendimiento con la búsqueda de texto completo, consulte la sección Rendimiento de los documentos de Django.

Buscar campo vectorial

Comience agregando un nuevo campo SearchVectorField al Quotemodelo en quotes/models.py :

from django.contrib.postgres.search import SearchVectorField  # new
from django.db import models


class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)
    search_vector = SearchVectorField(null=True)  # new

    def __str__(self):
        return self.quote

Cree el archivo de migración:

$ docker-compose exec web python manage.py makemigrations

Ahora, solo puede completar este campo cuando los objetos quoteo nameya existen en la base de datos. Por lo tanto, necesitamos agregar un activador para actualizar el search_vectorcampo cada vez que se actualicen los campos quoteo name. Para lograr esto, cree un archivo de migración personalizado en "quotes/migrations" llamado 0003_search_vector_trigger.py :

from django.contrib.postgres.search import SearchVector
from django.db import migrations


def compute_search_vector(apps, schema_editor):
    Quote = apps.get_model("quotes", "Quote")
    Quote.objects.update(search_vector=SearchVector("name", "quote"))


class Migration(migrations.Migration):

    dependencies = [
        ("quotes", "0002_quote_search_vector"),
    ]

    operations = [
        migrations.RunSQL(
            sql="""
            CREATE TRIGGER search_vector_trigger
            BEFORE INSERT OR UPDATE OF name, quote, search_vector
            ON quotes_quote
            FOR EACH ROW EXECUTE PROCEDURE
            tsvector_update_trigger(
                search_vector, 'pg_catalog.english', name, quote
            );
            UPDATE quotes_quote SET search_vector = NULL;
            """,
            reverse_sql="""
            DROP TRIGGER IF EXISTS search_vector_trigger
            ON quotes_quote;
            """,
        ),
        migrations.RunPython(
            compute_search_vector, reverse_code=migrations.RunPython.noop
        ),
    ]

Según la estructura de su proyecto, es posible que deba actualizar el nombre del archivo de migración anterior en formato dependencies.

Aplicar las migraciones:

$ docker-compose exec web python manage.py migrate

Para usar el nuevo campo para búsquedas, actualice SearchResultsListasí:

class SearchResultsList(ListView):
    model = Quote
    context_object_name = "quotes"
    template_name = "search.html"

    def get_queryset(self):
        query = self.request.GET.get("q")
        return Quote.objects.filter(search_vector=query)

Actualice nuevamente cotizaciones/templates/<li></li> search.html :

<li>{{ quote.quote | safe }} - <b>By <i>{{ quote.name }}</i></b></li>

Índice

Finalmente, configuremos un índice funcional, GinIndex .

Actualizar el Quotemodelo:

from django.contrib.postgres.indexes import GinIndex  # new
from django.contrib.postgres.search import SearchVectorField
from django.db import models


class Quote(models.Model):
    name = models.CharField(max_length=250)
    quote = models.TextField(max_length=1000)
    search_vector = SearchVectorField(null=True)

    def __str__(self):
        return self.quote

    # new
    class Meta:
        indexes = [
            GinIndex(fields=["search_vector"]),
        ]

Crea y aplica las migraciones por última vez:

$ docker-compose exec web python manage.py makemigrations
$ docker-compose exec web python manage.py migrate

Pruébelo.

Conclusión

En este tutorial, lo guiaron para agregar búsquedas básicas y de texto completo a una aplicación Django. También analizamos cómo optimizar la función de búsqueda de texto completo agregando un campo de vector de búsqueda y un índice de base de datos.

Tome el código completo del repositorio de django-search .

Fuente:  https://testdriven.io

#django #postgres 

Ahebwe  Oscar

Ahebwe Oscar

1624131000

Basic and Full-text Search with Django and Postgres

Unlike relational databases, full-text search is not standardized. There are a number of open-source options like ElasticSearch, Solr, and Xapian. ElasticSearch is probably the most popular solution; however, it’s complicated to set up and maintain. Further, if you’re not taking advantage of some of the advanced features that ElasticSearch offers, you should stick with the full-text search capabilities that many relational (like Postgres, MySQL, SQLite) and non-relational databases (like MongoDB and CouchDB) offer. Postgres in particular is well-suited for full-text search. Django supports it out-of-the-box as well.

For the vast majority of your Django apps, you should, at the very least, start out with leveraging full-text search from Postgres before looking to a more powerful solution like ElasticSearch or Solr.

In this article, we’ll add basic and full-text search to a Django app with Postgres.

Objectives

By the end of this article, you should be able to:

  1. Set up basic search functionality in a Django app with the Q object
  2. Add full-text search to a Django app
  3. Sort full-text search results by relevance using stemming, ranking, and weighting

#basic and full-text search with django and postgres #django #search lookup #postgres #full-text search #postgres full text search