索引¶
一个模型要提供搜索功能,需要将它加入到查询索引中。所有的页面、图片和文档已经默认加入了,所以可以方便在这些对象上搜索。
在``Page`` 或 Image
子类中定义的字段可能需要加入到索引中,以方便用户在这些字段中搜索相应的关键字,有关这方面的内容请参考 额外字段索引。
对于那些自定义模型,如果需要在其上面实现搜索功能,请参考 索引定制模型。
更新索引¶
如果查询索引与数据库相分离(例如使用 Elasticsearch 进行存贮),需要实现两者之间的数据同步。 有两种方式实现数据同步:使用查询信号处理句柄或定期调用 update_index
。
为满足速度以及可靠性,最好两种方式都使用。
信号处理句柄¶
wagtailsearch
信号处理句柄与所有索引模型的 save/delete 信号绑定。这将自动同步增加或删除底层平台(WAGTAILSEARCH_BACKENDS
)中的相应数据。
信号处理句柄在 wagtail.search
应用加载时进行的注册。
在某些情况下不希望进行索引的自动处理,而是调用 update_index
命令完成索引,这时可采用如下两种方法之一来实现:
禁用一个模型的自动更新信号处理句柄¶
在特定的模型类中定义 search_auto_update = False
来禁用。
禁用一个底层平台/网站的信号处理句柄¶
将配置文件中的 AUTO_UPDATE
置为 False
来实现网站级全部禁用索引自动同步功能。
有关 AUTO_UPDATE
配置的更多文档请参考 AUTO_UPDATE。
update_index
命令¶
Wagtail 提供了命令行方式的指令来实现索引重建。
./manage.py update_index
推荐每周执行一次这个命令,以及在发生以下情况时执行这个命令:
有页面通过脚本生成时(例如,执行了导入操作)
模型或搜索配置发生变化时
在执行更新索引命令时,界面执行的查询有可能返回空值,所以尽量不要在网站运行的高峰期执行命令。
注解
update_index
命令也使用别名 wagtail_update_index
命令,主要防止与其它安装包冲突,(例如 Haystack) 。
在这种情况下,其它安装在 INSTALLED_APPS
定义时应放在 wagtail.search
之前,这样就不会使用 Wagtail 的 update_index
命令了。
额外字段索引¶
警告
额外字段索引只在使用 Elasticsearch 平台 或 PostgreSQL 平台 情况下才能使用。数据库平台 (缺省) 不支持额外字段索引功能。
如果项目使用数据库做为底层索引平台,通过 search_fields
定义的字段将被忽略。
基于 Page
类定义的页面模型只有定义到 search_fields
属性的字段,在搜索或过滤时才纳入搜寻范围。
可以在子类中重新定义``search_fields` 并增加 SearchField
/FilterField
对象到其中。
实例¶
定义 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 + [ # Inherit search_fields from Page
index.SearchField('description'),
index.FilterField('date'),
]
# Get future events which contain the string "Christmas" in the title or description
>>> EventPage.objects.filter(date__gt=timezone.now()).search("Christmas")
index.SearchField
¶
使用全检索的方式来匹配关键词,一般用于文本字段。
选项¶
partial_match-部分匹配 (
boolean
) - 设为真时,匹配到单词部分字母时即为匹配成功。例如,页面标题即采用这种形式,当用户输入Hel``进行搜索时,标题为 ``Hello World!
的页面就匹配成功。boost (
int/float
) - 字段设置这个属性时可以定义字段匹配权重,更大的数字会表明匹配的权重高于其它字段。通过页面标题的值为 2,而其它字段的数值为 1.es_extra (
dict
) - 字段设置使用 Elasticsearch 时的字段映射属性字典,可以使用这个字段定义 Wagtail 尚未支持,但 Elasticsearch 支持的参数。
index.FilterField
¶
增加不使用全文搜索的字段索引。使用过滤器来过滤查询结果集。
索引调用方法及属性¶
注解
基于 数据库平台 (缺省) 的配置,不支持如下这些功能。
Search/filter 字段不一定是 Django 模型的字段类型,它们可以是类中的任意方法或属性。
用处之一是为``get_*_display`` 方法建立索引,Django 产生字段的选项列表。
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 the human-readable string for searching.
index.SearchField('get_is_private_display'),
# Index the boolean value for filtering.
index.FilterField('is_private'),
]
可调用的的方法也提供了从关联模型提供索引数据的功能。参考 Inline Panels and Model Clusters 的模型, 下面代码实现通过关联链接索引每本书的页面功能:
class BookPage(Page):
# ...
def get_related_link_titles(self):
# Get list of titles and concatenate them
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', partial_match=True, boost=10),
index.SearchField('get_genre_display'),
index.FilterField('genre'),
index.FilterField('author'),
index.FilterField('published_date'),
]
# As this model doesn't have a search method in its QuerySet, we have to call search directly on the backend
>>> from wagtail.search.backends import get_search_backend
>>> s = get_search_backend()
# Run a search for a book by 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>]