django.contrib.postgres.search
模块中的数据库功能可以轻松使用PostgreSQL的全文搜索引擎。
对于本文档中的示例,我们将使用Making queries中定义的模型。
请参见
有关搜索的高级概述,请参阅topic documentation。
search
查找¶使用全文搜索的最简单方法是针对数据库中的单个列搜索单个术语。 像这样:
>>> Entry.objects.filter(body_text__search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
这将在数据库中从body_text
字段和'Cheese'
中的plainto_tsquery
创建一个to_tsvector
都使用默认数据库搜索配置。 通过匹配查询和向量获得结果。
要使用search
查找,'django.contrib.postgres'
必须位于您的INSTALLED_APPS
中。
SearchVector
¶搜索单一的领域是伟大的但相当限制。 我们搜索的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
参数的说明,请参见Changing the search configuration和Weighting queries。
SearchQuery
¶SearchQuery
将用户提供的术语翻译成数据库与搜索向量进行比较的搜索查询对象。 默认情况下,用户提供的所有单词将通过词干算法进行传递,然后查找所有结果术语的匹配项。
SearchQuery
术语可以逻辑组合,提供更多的灵活性:
>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery('potato') & SearchQuery('ireland') # potato AND ireland
>>> SearchQuery('potato') | SearchQuery('penguin') # potato OR penguin
>>> ~SearchQuery('sausage') # NOT sausage
有关config
参数的说明,请参见Changing the search configuration。
SearchRank
¶到目前为止,我们刚刚返回了可以在向量和查询之间进行匹配的结果。 您可能希望通过某种相关性来排序结果。 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
参数的说明,请参见Weighting queries。
您可以将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
作为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')
特殊数据库配置不需要使用任何这些功能,但是,如果您搜索超过几百条记录,则可能会遇到性能问题。 例如,全文搜索比比较整数的大小更为重要。
如果您正在查询的所有字段都包含在一个特定模型中,则可以创建与要使用的搜索向量匹配的功能索引。 PostgreSQL文档有创建全文搜索索引的详细信息。
SearchVectorField
¶如果这种方法太慢,可以在模型中添加一个SearchVectorField
。 您需要使用触发器进行填充,例如,如PostgreSQL文档中所述。 然后,您可以查询该字段,就像它是一个带注释的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
查找之外,还可以使用其他几个表达式。
要使用它们,您需要激活PostgreSQL上的pg_trgm扩展名。 您可以使用TrigramExtension
迁移操作进行安装。
TrigramSimilarity
¶接受字段名称或表达式,以及字符串或表达式。 返回两个参数之间的三元组相似度。
用法示例:
>>> 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>]
TrigramDistance
¶接受字段名称或表达式,以及字符串或表达式。 返回两个参数之间的三元组距离。
用法示例:
>>> 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>]
2017年9月6日