Traducido por Miguel A. Ponce

documentación de Django - 5.2.15.dev20260527181452

Home | Table of contents | Index | Modules
« previous | up | next »

Búsqueda de texto completo¶

La función de la base de datos en el módulo django.contrib.postgres.search facilita el uso del motor de búsqueda de texto completo de PostgreSQL https://www.postgresql.org/docs/current/textsearch.html.

Para los ejemplos en este documento, utilizaremos los modelos definidos en Haciendo consultas.

Ver también

Para una visión general de alto nivel sobre la búsqueda, consulta la documentación del tema <topics/db/search>.

La búsqueda search¶

Una forma común de utilizar la búsqueda de texto completo es buscar un término único contra una columna única en la base de datos. Por ejemplo:

>>> Entry.objects.filter(body_text__search="Cheese")
<QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]>

Esto crea un to_tsvector en la base de datos desde el campo body_text y un plainto_tsquery del término de búsqueda 'Cheese', ambos utilizando la configuración de búsqueda por defecto de la base de datos. Los resultados se obtienen al coincidir la consulta y el vector.

Para utilizar la búsqueda search, debe tener 'django.contrib.postgres' en tu INSTALLED_APPS.

SearchVector¶

class SearchVector(*expressions, config=None, weight=None)[fuente]¶

Buscar contra un campo único es genial pero bastante limitante. Las instancias de Entry que estamos buscando pertenecen a un Blog, el cual tiene un campo tagline. Para consultar contra ambos campos, utilice un SearchVector:

>>> from django.contrib.postgres.search import SearchVector
>>> Entry.objects.annotate(
...     search=SearchVector("body_text", "blog__tagline"),
... ).filter(search="Cheese")
<QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]>

Los argumentos para SearchVector pueden ser cualquier Expression o el nombre de un campo. Si se proporcionan múltiples argumentos, se concatenarán entre sí utilizando un espacio, por lo que el documento de búsqueda incluirá todos ellos.

Los objetos SearchVector se pueden combinar entre sí, permitiendo reutilizarlos. Por ejemplo:

>>> Entry.objects.annotate(
...     search=SearchVector("body_text") + SearchVector("blog__tagline"),
... ).filter(search="Cheese")
<QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]>

Consulte Cambiar la configuración de búsqueda y Ponderando consultas para una explicación de los parámetros config y weight.

Búsqueda de Consulta¶

class SearchQuery(value, config=None, search_type='plain')[fuente]¶

Búsqueda de Consulta traduce los términos que proporciona el usuario en una consulta de búsqueda que la base de datos compara con un vector de búsqueda. Por defecto, se pasan todas las palabras que proporciona el usuario a través de los algoritmos de estemming y luego busca coincidencias para todos los términos resultantes.

Si search_type es 'plain', que es el valor por defecto, los términos se tratan como keywords separadas. Si search_type es 'phrase', los términos se tratan como una sola frase. Si search_type es 'raw', entonces puedes proporcionar una consulta de búsqueda formateada con términos y operadores. Si search_type es 'websearch', entonces puedes proporcionar una consulta de búsqueda formateada, similar a la utilizada por los motores de búsqueda web. 'websearch' requiere PostgreSQL ≥ 11. Lee los docs de Full Text Search de PostgreSQL para aprender sobre las diferencias y la sintaxis. Ejemplos:

>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery("red tomato")  # two keywords
>>> SearchQuery("tomato red")  # same results as above
>>> SearchQuery("red tomato", search_type="phrase")  # a phrase
>>> SearchQuery("tomato red", search_type="phrase")  # a different phrase
>>> SearchQuery("'tomato' & ('red' | 'green')", search_type="raw")  # boolean operators
>>> SearchQuery(
...     "'tomato' ('red' OR 'green')", search_type="websearch"
... )  # websearch operators

Los términos de Búsqueda de Consulta se pueden combinar lógicamente para proporcionar más flexibilidad:

>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery("meat") & SearchQuery("cheese")  # AND
>>> SearchQuery("meat") | SearchQuery("cheese")  # OR
>>> ~SearchQuery("meat")  # NOT

Consulta Cambiar la configuración de búsqueda para obtener una explicación del parámetro config.

Ranking de Búsqueda¶

class SearchRank(vector, query, weights=None, normalization=None, cover_density=False)[fuente]¶

Hasta ahora, hemos devuelto los resultados para los cuales cualquier coincidencia entre el vector y la consulta es posible. Es probable que desees ordenar los resultados por algún tipo de relevancia. PostgreSQL proporciona una función de ranking que tiene en cuenta cuántas veces los términos de la consulta aparecen en el documento, cómo cerca están los términos en el documento y qué parte del documento es donde ocurren. El mejor ajuste, mayor será el valor del rango. Para ordenar por relevancia:

>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
>>> vector = SearchVector("body_text")
>>> query = SearchQuery("cheese")
>>> Entry.objects.annotate(rank=SearchRank(vector, query)).order_by("-rank")
<QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]>

Consulta Ponderando consultas para obtener una explicación del parámetro weights.

Establece el parámetro cover_density en True para habilitar el ranking de densidad de cubierta, lo que significa que se tiene en cuenta la proximidad de los términos de consulta coincidentes.

Proporciona un entero al parámetro normalization para controlar la normalización del rango. Este entero es una máscara bit a bit, por lo que puedes combinar múltiples comportamientos:

>>> from django.db.models import Value
>>> Entry.objects.annotate(
...     rank=SearchRank(
...         vector,
...         query,
...         normalization=Value(2).bitor(Value(4)),
...     )
... )

La traducción de los textos es la siguiente:

TítuloDeBúsqueda¶

class SearchHeadline(expression, query, config=None, start_sel=None, stop_sel=None, max_words=None, min_words=None, short_word=None, highlight_all=None, max_fragments=None, fragment_delimiter=None)[fuente]¶

Acepta un campo de texto único o una expresión, una consulta, una configuración y un conjunto de opciones. Devuelve resultados de búsqueda resaltados.

Establezca los parámetros start_sel y stop_sel en los valores de cadena que se utilizarán para envolver los términos de la consulta resaltada en el documento. Los valores por defecto de PostgreSQL son <b> y </b>.

Proporcione valores enteros a los parámetros max_words y min_words para determinar las cabeceras más largas y cortas. Los valores por defecto de PostgreSQL son 35 y 15.

Proporcione un valor entero al parámetro short_word para descartar palabras de esta longitud o menos en cada cabecera. El valor por defecto de PostgreSQL es 3.

Establezca el parámetro highlight_all en True para utilizar todo el documento en lugar de un fragmento y ignorar los parámetros max_words, min_words y short_word. Eso está deshabilitado por defecto en PostgreSQL.

Proporcione un valor entero no cero al parámetro max_fragments para establecer el número máximo de fragmentos a mostrar. Eso está deshabilitado por defecto en PostgreSQL.

Establezca el parámetro de cadena fragment_delimiter para configurar el delimitador entre fragmentos. El valor por defecto de PostgreSQL es " ... ".

La documentación de PostgreSQL tiene más detalles sobre la resaltado de resultados de búsqueda.

Ejemplo de uso:

>>> from django.contrib.postgres.search import SearchHeadline, SearchQuery
>>> query = SearchQuery("red tomato")
>>> entry = Entry.objects.annotate(
...     headline=SearchHeadline(
...         "body_text",
...         query,
...         start_sel="<span>",
...         stop_sel="</span>",
...     ),
... ).get()
>>> print(entry.headline)
Sandwich with <span>tomato</span> and <span>red</span> cheese.

Consulta Cambiar la configuración de búsqueda para obtener una explicación del parámetro config.

Cambiar la configuración de búsqueda¶

Puedes especificar el atributo config a un SearchVector y SearchQuery para utilizar una diferente configuración de búsqueda. Esto permite usar diferentes analizadores de lenguaje y diccionarios como se definen en la base de datos:

>>> from django.contrib.postgres.search import SearchQuery, SearchVector
>>> Entry.objects.annotate(
...     search=SearchVector("body_text", config="french"),
... ).filter(search=SearchQuery("œuf", config="french"))
<QuerySet [<Entry: Pain perdu>]>

El valor de config también podría almacenarse en otra columna:

>>> from django.db.models import F
>>> Entry.objects.annotate(
...     search=SearchVector("body_text", config=F("blog__language")),
... ).filter(search=SearchQuery("œuf", config=F("blog__language")))
<QuerySet [<Entry: Pain perdu>]>

Ponderando consultas¶

No todos los campos pueden tener la misma relevancia en una consulta, por lo que puedes establecer pesos para varios vectores antes de combinarlos:

>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
>>> vector = SearchVector("body_text", weight="A") + SearchVector(
...     "blog__tagline", weight="B"
... )
>>> query = SearchQuery("cheese")
>>> Entry.objects.annotate(rank=SearchRank(vector, query)).filter(rank__gte=0.3).order_by(
...     "rank"
... )

El peso debe ser uno de las siguientes letras: D, C, B, A. Por defecto, estos pesos se refieren a los números 0.1, 0.2, 0.4 y 1.0, respectivamente. Si deseas ponderarlos de manera diferente, pasa una lista de cuatro flotantes a SearchRank como weights en el mismo orden anterior:

>>> rank = SearchRank(vector, query, weights=[0.2, 0.4, 0.6, 0.8])
>>> Entry.objects.annotate(rank=rank).filter(rank__gte=0.3).order_by("-rank")

Rendimiento¶

No es necesario ninguna configuración especial de la base de datos para utilizar alguna de estas funciones, sin embargo, si estás buscando más de un par de cientos de registros, probablemente te encontrarás con problemas de rendimiento. La búsqueda de texto completo es un proceso más intensivo que comparar el tamaño de un entero, por ejemplo.

En caso de que todos los campos que estés consultando se encuentren dentro de un modelo particular, puedes crear un índice funcional GIN o GiST que coincida con el vector de búsqueda deseado. Por ejemplo:

GinIndex(
    SearchVector("body_text", "headline", config="english"),
    name="search_vector_idx",
)

La documentación de PostgreSQL tiene detalles sobre crear índices para la búsqueda de texto completo.

SearchVectorField¶

class SearchVectorField[fuente]¶

Si este enfoque se vuelve demasiado lento, puedes agregar un SearchVectorField a tu modelo. Debes mantenerlo poblado con trigggers, por ejemplo, tal como se describe en la documentación de PostgreSQL. Puedes consultar el campo como si fuera una anotación SearchVector:

>>> Entry.objects.update(search_vector=SearchVector("body_text"))
>>> Entry.objects.filter(search_vector="cheese")
<QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]>

Similitud de trigramas¶

Otra forma de buscar es mediante similitud de trigramas. Un trigrama es un grupo de tres caracteres consecutivos. Además de los lookups trigram_similar, trigram_word_similar y trigram_strict_word_similar, puedes utilizar una pareja de expresiones.

Para usarlas, debes activar la extensión pg_trgm en PostgreSQL. Puedes instalarla utilizando la operación de migración TrigramExtension.

TrigramSimilarity¶

class TrigramSimilarity(expression, string, **extra)[fuente]¶

Aceptar un nombre de campo o expresión, y una cadena o expresión. Devuelve la similitud de trigramas entre los dos argumentos.

Ejemplo de uso:

>>> from django.contrib.postgres.search import TrigramSimilarity
>>> Author.objects.create(name="Katy Stevens")
>>> Author.objects.create(name="Stephen Keats")
>>> test = "Katie Stephens"
>>> Author.objects.annotate(
...     similarity=TrigramSimilarity("name", test),
... ).filter(
...     similarity__gt=0.3
... ).order_by("-similarity")
<QuerySet [<Author: Katy Stevens>, <Author: Stephen Keats>]>

TrigramWordSimilarity¶

class TrigramWordSimilarity(string, expression, **extra)[fuente]¶

Aceptar una cadena o expresión, y un nombre de campo o expresión. Devuelve la similitud de palabras de trigramas entre los dos argumentos.

Ejemplo de uso:

>>> from django.contrib.postgres.search import TrigramWordSimilarity
>>> Author.objects.create(name="Katy Stevens")
>>> Author.objects.create(name="Stephen Keats")
>>> test = "Kat"
>>> Author.objects.annotate(
...     similarity=TrigramWordSimilarity(test, "name"),
... ).filter(
...     similarity__gt=0.3
... ).order_by("-similarity")
<QuerySet [<Author: Katy Stevens>]>

TrigramStrictWordSimilarity¶

class TrigramStrictWordSimilarity(string, expression, **extra)[fuente]¶

Aceptar una cadena o expresión, y un nombre de campo o expresión. Devuelve la similitud estricta de palabras de trigramas entre los dos argumentos. Similar a TrigramWordSimilarity(), excepto que fuerza las fronteras de extensión para coincidir con las fronteras de palabra.

TrigramDistance¶

class TrigramDistance(expression, string, **extra)[fuente]¶

Acepta un nombre de campo o expresión, y una cadena o expresión. Devuelve la distancia trigrámica entre los dos argumentos.

Ejemplo de uso:

>>> from django.contrib.postgres.search import TrigramDistance
>>> Author.objects.create(name="Katy Stevens")
>>> Author.objects.create(name="Stephen Keats")
>>> test = "Katie Stephens"
>>> Author.objects.annotate(
...     distance=TrigramDistance("name", test),
... ).filter(
...     distance__lte=0.7
... ).order_by("distance")
<QuerySet [<Author: Katy Stevens>, <Author: Stephen Keats>]>

TrigramWordDistance¶

class TrigramWordDistance(string, expression, **extra)[fuente]¶

Acepta una cadena o expresión, y un nombre de campo o expresión. Devuelve la distancia trigrámica de palabras entre los dos argumentos.

Ejemplo de uso:

>>> from django.contrib.postgres.search import TrigramWordDistance
>>> Author.objects.create(name="Katy Stevens")
>>> Author.objects.create(name="Stephen Keats")
>>> test = "Kat"
>>> Author.objects.annotate(
...     distance=TrigramWordDistance(test, "name"),
... ).filter(
...     distance__lte=0.7
... ).order_by("distance")
<QuerySet [<Author: Katy Stevens>]>

TrigramStrictWordDistance¶

class TrigramStrictWordDistance(string, expression, **extra)[fuente]¶

Acepta una cadena o expresión, y un nombre de campo o expresión. Devuelve la distancia trigrámica estricta de palabras entre los dos argumentos.

Tabla de contenido

  • Búsqueda de texto completo
    • La búsqueda search
    • SearchVector
    • Búsqueda de Consulta
    • Ranking de Búsqueda
    • TítuloDeBúsqueda
    • Cambiar la configuración de búsqueda
    • Ponderando consultas
    • Rendimiento
      • SearchVectorField
    • Similitud de trigramas
      • TrigramSimilarity
      • TrigramWordSimilarity
      • TrigramStrictWordSimilarity
      • TrigramDistance
      • TrigramWordDistance
      • TrigramStrictWordDistance

Tema anterior

Operaciones de migración de la base de datos

Próximo tema

Validadores

Esta página

  • Mostrar el código

Búsqueda rápida

Last update:

may 31, 2026

« previous | up | next »