索引 ( Indexing )
• 最后修改:2024-05-04 • 阅读量:36
要使模型可搜索,您需要将其添加到搜索索引中。所有页面、图像和文档均已为您建立索引,因此您可以立即开始搜索它们。
如果您在 Page 或 Image 的子类中创建了一些额外字段,您可能还希望将这些新字段添加到搜索索引中,以便用户的搜索查询与其内容相匹配。有关如何执行此操作的信息,请参阅 索引额外字段 。
如果您有想要可搜索的自定义模型,请参阅 索引自定义模型 。
更新索引
如果搜索索引与数据库分开(例如使用 Elasticsearch 时),则需要使它们保持同步。有两种方法可以做到这一点:使用搜索信号处理程序,或定期调用 update_index
命令。为了获得最佳速度和可靠性,最好尽可能同时使用两者。
信号处理程序
wagtailsearch
提供了一些信号处理程序,绑定到所有索引模型的保存/删除信号。这会自动从您在 WAGTAILSEARCH_BACKENDS
中注册的所有后端添加和删除它们。加载 wagtail.search
应用程序时,会自动注册这些信号处理程序。
在某些情况下,您可能不希望自动重新索引内容,而是依赖 update_index
命令进行索引。如果您需要禁用这些信号处理程序,请使用以下方法之一:
禁用模型的自动更新信号处理程序
您可以通过添加 search_auto_update = False
作为模型类的属性来禁用单个模型的信号处理程序。
禁用搜索后端/整个站点的自动更新信号处理程序
您可以通过将后端上的 AUTO_UPDATE
设置设置为 False
来禁用整个搜索后端的信号处理程序。
如果所有搜索后端将 AUTO_UPDATE
设置为 False
,则整个站点的信号处理程序将被完全禁用。
有关 AUTO_UPDATE
设置的文档,请参阅 AUTO_UPDATE 。
update_index
命令
Wagtail 还提供了从头开始重建索引的命令。
./manage.py update_index
建议每周运行一次此命令,并在以下时间运行:
- 每当通过脚本创建任何页面时(例如导入后)
- 每当对模型或搜索配置进行任何更改时
运行此命令时,搜索可能不会返回任何结果,因此请避免在高峰时间运行它。
注意:
updateindex
命令也别名为 wagtailupdateindex
,用于当另一个已安装的软件包(例如 Haystack )提供冲突的 updateindex
命令时使用。在这种情况下, INSTALLEDAPPS
中其他软件包的条目应出现在 wagtail.search
之上,以便其 updateindex
命令优先于 Wagtail 的命令。 {class="text-success"}
禁用模型索引
通过在模型中设置 search_fields =[]
,可以完全禁用模型的索引。这将禁用信号处理程序和 update_index
管理命令的索引更新。
索引额外字段
字段必须显式添加到 Page
派生模型的 search_fields
属性中,以便您能够搜索/过滤它们。这是通过覆盖 search_fields
向其附加额外的 SearchField
/ FilterField
对象列表来完成的。
Example
这将创建一个具有两个字段的 EventPage
模型: description
和 date
。 description
索引为 SearchField
, date
索引为 FilterField
。
from wagtail.search import index
from django.utils import timezone
class EventPage(Page):
description = models.TextField()
date = models.DateField()
search_fields = Page.search_fields + [ # 从Page继承search_fields
index.SearchField('description'),
index.FilterField('date'),
]
# 获取标题或描述中包含字符串 "Christmas" 的未来事件
>>> EventPage.objects.filter(date__gt=timezone.now()).search("Christmas")
index.SearchField
它们用于在模型上执行全文搜索,通常用于文本字段。
选项
-
boost (
int/float
) - 这允许您将字段设置为比其他字段更重要。在字段上将此值设置为较高的数字将导致该字段中匹配的页面排名更高。默认情况下,页面标题字段设置为 2,所有其他字段设置为 1。注意:
PostgresSQL全文搜索仅支持 four weight levels (A, B, C, D) 。当数据库搜索后端wagtail.search.backends.database
用于 PostgreSQL 数据库时,它将考虑项目中的所有 boost 值,并将它们分组为四个可用权重。
这意味着,在此配置中,即使使用了更多的提升值,实际上也仅使用四个提升级别来对搜索结果进行排名。
通过使用./manage.py shell
启动新的 Django shell 并检查wagtail.search.backends.database.postgres.weights.BOOST_WEIGHTS
,您可以大致找出哪些提升阈值映射到 PostgresSQL 中的哪个权重。您应该看到类似[(10.0, 'A'), (7.166666666666666, 'B'), (4.333333333333333, 'C'), (1.5, 'D')]
的内容。高于每个阈值的提升值将使用相应的权重进行处理。 -
es_extra (
dict
) - 该字段允许开发人员设置或覆盖 Elasticsearch 映射中该字段的任何设置。如果您想使用 Wagtail 尚不支持的任何 Elasticsearch 功能,请使用此选项。
index.AutocompleteField
这些用于匹配部分单词的自动完成查询。例如,如果用户仅在搜索框中键入 Hel
,就会找到标题为 Hello World!
的页面。
这采用与 index.SearchField
完全相同的选项。
注意:
仅对搜索结果中显示的字段使用 index.AutocompleteField
进行索引。这允许用户查看部分匹配的任何单词。 {class="text-success"}
index.FilterField
这些将添加到搜索索引中,但不用于全文搜索。相反,它们允许您对搜索结果运行过滤器。
index.RelatedFields
这允许您从相关对象中索引字段。它适用于所有类型的相关字段,包括它们的反向访问器。
例如,如果我们有一本作者为 ForeignKey
的书,我们可以将作者的 name
和 date_of_birth
字段嵌套在书中:
from wagtail.search import index
class Book(models.Model, index.Indexed):
...
search_fields = [
index.SearchField('title'),
index.FilterField('published_date'),
index.RelatedFields('author', [
index.SearchField('name'),
index.FilterField('date_of_birth'),
]),
]
这将允许您按作者姓名搜索书籍。
反之亦然。您可以对作者的书籍进行索引,从而允许按作者出版的书籍的标题搜索作者:
from wagtail.search import index
class Author(models.Model, index.Indexed):
...
search_fields = [
index.SearchField('name'),
index.FilterField('date_of_birth'),
index.RelatedFields('books', [
index.SearchField('title'),
index.FilterField('published_date'),
]),
]
依据 index.RelatedFields
过滤
无法使用 QuerySet
API 过滤 index.RelatedFields
中的任何 index.FilterFields
。但是,这些字段已建立索引,因此应该可以通过手动查询 Elasticsearch 来使用它们。
计划在 Wagtail 的未来版本中使用 QuerySet
API 对 index.RelatedFields
进行过滤。
索引可调用对象和其他属性
搜索/过滤字段不需要是 Django 模型字段。它们也可以是模型类上的任何方法或属性。
其用途之一是为 Django 自动为带有选择的字段创建的 get_*_display
方法建立索引。
from wagtail.search import index
class EventPage(Page):
IS_PRIVATE_CHOICES = (
(False, "Public"),
(True, "Private"),
)
is_private = models.BooleanField(choices=IS_PRIVATE_CHOICES)
search_fields = Page.search_fields + [
# 为人类可读的字符串建立索引以进行搜索。
index.SearchField('get_is_private_display'),
# 索引 boolean 值进行过滤。
index.FilterField('is_private'),
]
Callables 还提供了一种从相关模型中索引字段的方法。在 [InlinePanel] 的示例中,通过相关链接的标题对每个 BookPage 进行索引:
class BookPage(Page):
# ...
def get_related_link_titles(self):
# 获取标题列表并将它们连接起来
return '\n'.join(self.related_links.all().values_list('name', flat=True))
search_fields = Page.search_fields + [
# ...
index.SearchField('get_related_link_titles'),
]
索引自定义模型
任何 Django 模型都可以被索引和搜索。
为此,请继承 index.Indexed
并向模型添加一些 search_fields
。
from wagtail.search import index
class Book(index.Indexed, models.Model):
title = models.CharField(max_length=255)
genre = models.CharField(max_length=255, choices=GENRE_CHOICES)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
published_date = models.DateTimeField()
search_fields = [
index.SearchField('title', boost=10),
index.AutocompleteField('title', boost=10),
index.SearchField('get_genre_display'),
index.FilterField('genre'),
index.FilterField('author'),
index.FilterField('published_date'),
]
# 由于该模型的 QuerySet 中没有搜索方法,因此我们必须直接在后端调用搜索
>>> from wagtail.search.backends import get_search_backend
>>> s = get_search_backend()
# 搜索 Roald Dahl 的书
>>> roald_dahl = Author.objects.get(name="Roald Dahl")
>>> s.search("chocolate factory", Book.objects.filter(author=roald_dahl))
[<Book: Charlie and the chocolate factory>]