Django 6.0.dev 文档

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

全文搜索¶

数据库函数 django.contrib.postgres.search 模块简化了PostgreSQL的使用 full text search engine .

对于本文档中的示例,我们将使用中定义的模型 进行查询 .

参见

有关搜索的高级概述,请参见 topic documentation .

这个 search 查找¶

使用全文搜索的一种常见方法是针对数据库中的单个列搜索单个术语。例如:

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

这创造了一个 to_tsvector 在数据库中 body_text 场与A plainto_tsquery 从搜索词 'Cheese' ,都使用默认的数据库搜索配置。结果是通过匹配查询和向量得到的。

使用 search 查找, 'django.contrib.postgres' 一定在你 INSTALLED_APPS .

SearchVector¶

class SearchVector(*expressions, config=None, weight=None)[源代码]¶

针对单个领域进行搜索是很棒的,但也相当有限。这个 Entry 我们正在搜索的实例属于 Blog ,它有一个 tagline 菲尔德。若要针对这两个字段进行查询,请使用 SearchVector :

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

的论据 SearchVector 可以是任何 Expression 或者字段的名称。多个参数将使用空格连接在一起,以便搜索文档将它们全部包含在内。

SearchVector 对象可以组合在一起,允许您重复使用它们。例如:

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

见 更改搜索配置 和 加权查询 为了解释 config 和 weight 参数。

SearchQuery¶

class SearchQuery(value, config=None, search_type='plain')[源代码]¶

SearchQuery 将用户提供的术语转换为数据库与搜索向量进行比较的搜索查询对象。默认情况下,用户提供的所有单词都将通过词干算法传递,然后它将查找所有生成的术语的匹配项。

如果 search_type 是 'plain' ,这是默认情况,这些术语被视为单独的关键字。如果 search_type 是 'phrase' ,这些术语被视为一个短语。如果 search_type 是 'raw' ,然后您可以提供包含术语和运算符的格式化搜索查询。如果 search_type 是 'websearch' ,然后您可以提供格式化的搜索查询,类似于网络搜索引擎使用的搜索查询。 'websearch' 要求PostgreSQL = 11。阅读PostgreSQL Full Text Search docs 了解差异和语法。例子:

>>> 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

SearchQuery 术语可以逻辑组合,以提供更大的灵活性:

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

见 更改搜索配置 为了解释 config 参数。

SearchRank¶

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

到目前为止,我们已经返回了矢量和查询之间可能存在任何匹配的结果。您可能希望按某种相关性对结果进行排序。PostgreSQL提供了一个排名功能,该功能考虑了查询词语在文档中出现的频率、词语在文档中的距离有多近,以及文档中它们出现的位置有多重要。比赛越好,排名就越高。按相关性排序:

>>> 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")
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]

见 加权查询 为了解释 weights 参数。

设置 cover_density 参数设置为 True 启用覆盖密度排名,这意味着要考虑匹配查询词的接近度。

将一个整数提供给 normalization 参数来控制等级归一化。此整数是位掩码,因此可以组合多个行为:

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

PostgreSQL文档包含有关以下的更多详细信息 different rank normalization options 。

SearchHeadline¶

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)[源代码]¶

接受单个文本字段或运算式、查询、配置和一组选项。返回突出显示的搜索结果。

设置 start_sel 和 stop_sel 参数为字符串值,用于包装文档中突出显示的查询项。PostgreSQL的默认值是 <b> 和 </b> 。

为 max_words 和 min_words 确定最长和最短头条新闻的参数。PostgreSQL的默认值是35和15。

为 short_word 参数用于丢弃每个标题中此长度或更短的单词。PostgreSQL的默认值是3。

设置 highlight_all 参数设置为 True 使用整个文档代替片段并忽略 max_words , min_words ,以及 short_word 参数在PostgreSQL中默认禁用该功能。

为 max_fragments 设置要显示的最大片段数。在PostgreSQL中默认禁用该功能。

设置 fragment_delimiter 字符串参数用于配置片段之间的字节。PostgreSQL的默认值是 " ... " 。

PostgreSQL文档有更多详细信息 highlighting search results 。

使用示例:

>>> 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.

见 更改搜索配置 为了解释 config 参数。

更改搜索配置¶

您可以指定 config 属性添加到 SearchVector 和 SearchQuery 要使用其他搜索配置,请执行以下操作。这允许使用数据库定义的不同语言解析器和词典:

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

的价值 config 也可以存储在另一列中:

>>> 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")))
[<Entry: Pain perdu>]

加权查询¶

查询中的每个字段可能不具有相同的相关性,因此您可以在组合各种向量之前设置它们的权重:

>>> 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"
... )

权重应为以下字母之一:D、C、B、A。默认情况下,这些权重指的是数字 0.1 , 0.2 , 0.4 ,以及 1.0 ,分别为。如果希望对它们进行不同的加权,请将四个浮点数的列表传递给 SearchRank AS weights 按上述顺序排列:

>>> 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")

性能¶

使用这些函数不需要特殊的数据库配置,但是,如果搜索的记录超过数百条,则可能会遇到性能问题。例如,全文搜索比比较整数的大小更为密集。

如果要查询的所有字段都包含在一个特定模型中,则可以创建一个函数 GIN 或 GiST 与您要使用的搜索向量匹配的索引。例如::

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

PostgreSQL文档包含有关的详细信息 creating indexes for full text search 。

SearchVectorField¶

class SearchVectorField[源代码]¶

如果此方法变得太慢,您可以添加一个 SearchVectorField 敬你的模特。例如,您需要保持使用触发器填充它,如 PostgreSQL documentation 。然后,您可以查询该字段,就像它是一个带注释的 SearchVector :

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

三元相似度¶

另一种搜索方法是三元组相似度。三文法是由三个连续字符组成的一组。除 trigram_similar , trigram_word_similar ,以及 trigram_strict_word_similar 查找时,您可以使用其他几个表达式。

要使用它们,需要激活 pg_trgm extension 在PostgreSQL上。您可以使用 TrigramExtension 迁移操作。

TrigramSimilarity¶

class TrigramSimilarity(expression, string, **extra)[源代码]¶

接受字段名或表达式以及字符串或表达式。返回两个参数之间的三元相似性。

使用示例:

>>> 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")
[<Author: Katy Stevens>, <Author: Stephen Keats>]

TrigramWordSimilarity¶

class TrigramWordSimilarity(string, expression, **extra)[源代码]¶

接受字符串或表达式以及字段名或表达式。返回两个参数之间的三元组单词相似度。

使用示例:

>>> 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")
[<Author: Katy Stevens>]

TrigramStrictWordSimilarity¶

class TrigramStrictWordSimilarity(string, expression, **extra)[源代码]¶

接受字符串或表达式以及字段名或表达式。返回两个参数之间的三元组严格单词相似度。类似于 TrigramWordSimilarity() ,除非它强制范围边界与字边界相匹配。

TrigramDistance¶

class TrigramDistance(expression, string, **extra)[源代码]¶

接受字段名或表达式以及字符串或表达式。返回两个参数之间的三角距离。

使用示例:

>>> 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")
[<Author: Katy Stevens>, <Author: Stephen Keats>]

TrigramWordDistance¶

class TrigramWordDistance(string, expression, **extra)[源代码]¶

接受字符串或表达式以及字段名或表达式。返回两个参数之间的三元组单词距离。

使用示例:

>>> 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")
[<Author: Katy Stevens>]

TrigramStrictWordDistance¶

class TrigramStrictWordDistance(string, expression, **extra)[源代码]¶

接受字符串或表达式以及字段名或表达式。返回两个参数之间的三元组严格单词距离。

目录

  • 全文搜索
    • 这个 search 查找
    • SearchVector
    • SearchQuery
    • SearchRank
    • SearchHeadline
    • 更改搜索配置
    • 加权查询
    • 性能
      • SearchVectorField
    • 三元相似度
      • TrigramSimilarity
      • TrigramWordSimilarity
      • TrigramStrictWordSimilarity
      • TrigramDistance
      • TrigramWordDistance
      • TrigramStrictWordDistance

上一主题

数据库迁移操作

下一主题

验证器

快速搜索

Last update:

5月 28, 2025

« previous | up | next »