Skip to content

djangodocs

Django 3.2
  • 6.1 current
  • 6.0
  • 5.2 LTS
  • 5.1 unsupported
  • 5.0 unsupported
  • 4.2 unsupported
  • 4.1 unsupported
  • 4.0 unsupported
  • 3.2 unsupported
  • 3.1 unsupported
  • 3.0 unsupported
  • 2.2 unsupported
  • 2.1 unsupported
  • 2.0 unsupported
简体中文
  • English
  • 简体中文
  • Français
  • 日本語
  • Bahasa Indonesia
  • Italiano
  • Português (Brasil)
  • 한국어
  • Español
  • Ελληνικά
  • Polski
Documentation contents
  • Django 文档
  • 开始
  • 使用 Django
  • 操作指南
  • Django FAQ
  • API 参考
    • 应用程序
    • 系统检查框架
    • 内置基于类的视图 API
    • 点击劫持保护
    • contrib 包
      • Django 管理站点
      • django.contrib.auth
      • 内容类型框架
      • 简单页面应用
      • GeoDjango
      • django.contrib.humanize
      • 消息框架
      • django.contrib.postgres
        • PostgreSQL 特有聚合函数
        • PostgreSQL 特有数据库约束
        • PostgreSQL 特有模型字段
        • PostgreSQL 特有表单字段和部件
        • PostgreSQL 特有数据库函数
        • PostgreSQL 特有模型索引
        • PostgreSQL 特有查找
        • 数据库迁移操作
        • 全文搜索
        • 验证器
      • 重定向应用
      • 站点地图框架
      • “站点”框架
      • staticfiles 应用
      • Feed 聚合框架
    • 跨站请求伪造保护
    • 数据库
    • django-admin 和 manage.py
    • Django 异常
    • 文件处理
    • 表单
    • 中间件
    • 迁移操作
    • 模型
    • 分页器
    • 请求和响应对象
    • SchemaEditor
    • 配置
    • 信号
    • 模板
    • TemplateResponse 和 SimpleTemplateResponse
    • Unicode 数据
    • django.urls 实用函数
    • URLconfs 中使用的 django.urls 函数
    • Django 实用程序
    • 验证器
    • 内置视图
  • 元文件和杂记
  • 术语
  • 发行说明
  • Django internals
Django 3.2 is no longer supported. It receives no security fixes. Use it for reference only. Latest release
Chinese (Simplified) translation. Contributed by the Django community. 75.8% Help translate
  1. Django 3.2
  2. API 参考
  3. contrib 包
  4. django.contrib.postgres

全文搜索Link to this heading#

django.contrib.postgres.search 模块中的数据库函数方便了 PostgreSQL 的 全文搜索引擎 的使用。

在本文档的例子中,我们将使用 执行查询 中定义的模型。

See also

有关搜索的高级概述,请参见 主题文档。

search 查找Link to this heading#

使用全文检索的常见方法是针对数据库中的单一列进行单项检索。例如:

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

这将使用默认的数据库搜索配置,从 body_text 字段在数据库中创建一个 to_tsvector,从搜索词 'Cheese' 中创建一个 plainto_tsquery。通过匹配查询和向量得到结果。

要使用 search 查找,'django.contrib.postgres' 必须在你的 INSTALLED_APPS。

Changed in Django 3.1

增加了对查询表达式的支持。

SearchVectorLink to this heading#

class SearchVector(*expressions, config=None, weight=None)Link to this definition#

对单个字段进行搜索是很好的,但有很大的局限性。我们要搜索的 Entry 实例属于 Blog,它有一个 tagline 字段。要对这两个字段进行查询,使用 SearchVector:

Code
>>> 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 对象可以组合在一起,允许你重复使用它们。例如:

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

关于 config 和 weight 参数的解释,请参见 更改搜索配置 和 加权查询。

SearchQueryLink to this heading#

class SearchQuery(value, config=None, search_type='plain')Link to this definition#

SearchQuery 将用户提供的术语转化为搜索查询对象,数据库将其与搜索向量进行比较。默认情况下,用户提供的所有词语都会通过词干算法,然后寻找所有结果词语的匹配。

如果 search_type 是 'plain',即默认值,则将术语作为单独的关键字处理。如果 search_type 是 'phrase',则将术语作为一个单一的短语处理。如果 search_type 是 'raw',那么你可以提供一个带有术语和运算符的格式化搜索查询。如果 search_type 是 'websearch',那么你可以提供一个格式化的搜索查询,类似于网络搜索引擎使用的格式。'websearch' 需要 PostgreSQL ≥ 11。请阅读 PostgreSQL 的 全文搜索文档 来了解两者的区别和语法。举例说明。

Code
>>> 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 术语可以按逻辑组合,以提供更大的灵活性:

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

参见 更改搜索配置 对 config 参数的解释。

Changed in Django 3.1

在 SearchQuery.value 中增加了对 'websearch' 搜索类型和查询表达式的支持。

SearchRankLink to this heading#

class SearchRank(vector, query, weights=None, normalization=None, cover_density=False)Link to this definition#

到目前为止,我们已经返回了向量和查询之间可能匹配的结果。很可能你会希望按照某种相关性对结果进行排序。PostgreSQL 提供了一个排序函数,它考虑了查询术语在文档中出现的频率,术语在文档中的相近程度,以及它们出现的部分在文档中的重要性。匹配度越高,排名值越高。要按相关性排序:

Code
>>> 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 参数提供一个整数,以控制等级标准化。这个整数是一个位掩码,所以你可以结合多种行为:

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

PostgreSQL 文档中有更多关于 不同排序归一化选项 的细节。

New in Django 3.1

增加了 normalization 和 cover_density 参数。

SearchHeadlineLink to this heading#

New in Django 3.1

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)Link to this definition#

接受一个文本字段或一个表达式、一个查询、一个配置和一组选项。返回高亮显示的搜索结果。

将 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 文档中有更多关于 高亮搜索结果 的细节。

使用实例:

Code
>>> 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 参数的解释。

更改搜索配置Link to this heading#

你可以为 SearchVector 和 SearchQuery 指定 config 属性,以使用不同的搜索配置。这允许使用数据库定义的不同语言解析器和字典:

Code
>>> 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 的值也可以储存在另一列中:

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

加权查询Link to this heading#

每个字段在查询中的相关度可能不一样,所以在组合之前可以设置各种向量的权重:

Code
>>> 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')

权重应该是下列字母之一。默认情况下,这些权重分别是指数字 0.1、0.2、0.4 和 1.0。如果你希望以不同的方式对它们进行加权,请将四个浮点数的列表传递给 SearchRank 作为 weights,顺序与上述相同:

Code
>>> 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')

性能Link to this heading#

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

如果你要查询的所有字段都包含在一个特定的模型中,你可以创建一个与你希望使用的搜索向量相匹配的功能索引。PostgreSQL 文档中有关于 为全文搜索创建索引 的详细介绍。

SearchVectorFieldLink to this heading#

class SearchVectorFieldLink to this definition#

如果这种方法变得太慢,你可以在你的模型中添加一个 SearchVectorField。你需要用触发器来填充它,例如,如 PostgreSQL 文档 中所述。然后,你可以像查询一个注解的 SearchVector 一样查询这个字段:

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

三元相似度Link to this heading#

另一种搜索方法是三元相似度。trigram 是一组连续的三个字符。除了 trigram_similar 查找之外,你还可以使用其他几个表达式。

要使用它们,你需要激活 PostgreSQL 上的 pg_trgm 扩展 。你可以使用 TrigramExtension 迁移操作来安装它。

TrigramSimilarityLink to this heading#

class TrigramSimilarity(expression, string, **extra)Link to this definition#

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

使用实例:

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

TrigramDistanceLink to this heading#

class TrigramDistance(expression, string, **extra)Link to this definition#

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

使用实例:

Code
>>> 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>]
View as Markdown Edit this page on GitHub Official version
Previous数据库迁移操作 Next验证器

On this page

  • search 查找
  • SearchVector
  • SearchQuery
  • SearchRank
  • SearchHeadline
  • 更改搜索配置
  • 加权查询
  • 性能
    • SearchVectorField
  • 三元相似度
    • TrigramSimilarity
    • TrigramDistance

An unofficial rendering of the Django documentation.

Not affiliated with or endorsed by the Django Software Foundation. The documentation is copyright © Django Software Foundation and individual contributors, and is used under the BSD 3-Clause licence. “Django” is a trademark of the Django Software Foundation.

This translation is the work of the Django i18n community, not of this site. Read the official documentation at docs.djangoproject.com.

👋 Jason Cartwright