索引的建立

要令到模型可视化,就需要将其加入到搜索索引中。所有页面、图片与文档都被索引起来,那么就可以立即开始对他们进行搜索了。

在某个页面或图片基类的子类中建立了额外字段时,可能会将这些新的字段,也加入到搜索索引中,从而令到用户的搜索查询,对这些子类的内容进行匹配。请参阅对额外字段建立索引

在希望将定制模型纳入搜索时,请参阅建立定制模型的索引

更新索引

在搜索索引与数据库分离的情况下(比如使用Elesticsearch时),就要让二者保持同步状态。有两种方式可以完成此操作:使用搜索信号处理器,或周期性地调用update_index命令。处于最佳速度与可靠性的考虑,最好的做法是在可能的情况下二者同时使用。

关于信号处理器

wagtailsearch库提供了一些绑定到所有已索引模型的保存/删除信号的信号处理器。这将自动在已于WAGTAILSEARCH_BACKENDS中注册的所有后端中,添加及删除相应他们。在wagtail.search应用装入时,这些信号处理器自动进行了注册。

关于update_index命令

Wagtail还提供了用于从头开始重建索引的一个命令

  1. ./manage.py update_index

推荐每周运行一次此命令,以及在以下时刻运行他:

  • 在经由脚本(比如导入内容后)创建了页面后
  • 在对模型或搜索的配置进行了修改之后

因为此命令运行时的搜索不会返回结果,因此要避免在峰值时段运行此命令。

对额外字段进行索引

警告 数据库后端并不支持对额外字段的索引。在使用数据库后端是,经由search_fields所定义的所有其他字段,都会被忽略。

必要要将字段显式地加入到那些由Page基类所派生的模型的search_fields字段,以便对这些字段进行搜索/过滤。这是通过对search_fields进行覆写,来将一个额外的SearchField/FilterField字段给他,而完成的。

示例

下面的代码创建了有着两个字段的EventPage模型:descriptiondatedescription作为了SearchField进行索引,而date则作为FilterField进行索引。

  1. from watail.search import index
  2. from django.utils import timezone
  3. class EventPage(Page):
  4. description = models.TextField()
  5. date = models.DateField()
  6. search_fields = Page.search_fields + [ # 这里从 Page 基类继承 search_fields
  7. index.SearchField('description'),
  8. index.FilterField('date'),
  9. ]
  10. # 获取在标题或活动描述中包含 “Christmas” 字符串的未来活动
  11. >>> EventPage.objects.filter(date__gt=timezone.now()).search("Christmas")

关于index.SearchField

指定用于在模型上执行全文搜索的字段,通常是指文本字段。

选项

  • partial_match(boolean) — 将该选项设置为真时,允许结果在部分词上匹配。比如此选项默认对标题就设置为真,那么在某个页面的标题为Hello World!时,若用户在搜索框中输入的是Hel,则该页面将会被找到。

  • boost(int/float) — 此选项允许将一些字段设置为较其他字段更为重要。将某字段的此选项设置为一个较高的数字,将那些在该字段匹配的页面,在结果共排序靠前。通常页面标题字段的该选项被设置为2,所有其他字段的该选项被设置为1

  • es_extra(dict) — 指定该字段允许开发者设置或覆写Elasticsearch映射中该字段上的所有设置。在打算使用某些Wagtail尚不支持的Elasticsearch的特性时,就要用到此选项。

关于index.FilterField

指定要加入到搜索索引的字段,但这些字段不用于全文搜索。而是可以在搜索结果上运行过滤器。

关于index.RelatedFields

此特性允许对相关对象的字段进行索引。其工作于相关字段的所有类型,包含他们的反向访问器(This allows you to index fields from related objects. It works on all types of related fields, including their reverse accessors)。

比如这里有一个到书籍作者的ForeignKey,就可以将作者模型的namedate_of_birth字段,嵌入到书籍模型内:

  1. from wagtail.search import index
  2. class Book(models.Model, index.Indexed):
  3. ...
  4. search_fields = [
  5. index.SearchField('title'),
  6. index.FilterField('published_date'),
  7. index.RelatedFields('author', [
  8. index.SearchField('name'),
  9. index.FilterField('date_of_birth'),
  10. ]),
  11. ]

index.RelatedFields上的过滤

使用QuerySet编程接口在index.RelatedFields中的所有index.FilterFields上进行过滤,都是不可能的。不过这些字段既然有被索引起来,那么就有可能通过手动查询Elasticsearch来用到他们。

Wagtail计划在未来的发行中,实现经由QuerySetindex.RelatedFields上的过滤。

对可调用及其他属性的索引

Indexing callables and other attributes

注意 数据库后端(默认) 不支持此特性。

搜索/过滤器字段无需是Django模型字段。他们还可以是模型类的方法或属性。

此特性的一种用处,是对那些Django自动创建的、带有选项的字段的get_*_display方法的索引。

  1. from wagtail.search import index
  2. class EventPage(Page):
  3. IS_PRIVATE_CHOICES = (
  4. (False, "公开的"),
  5. (False, "私有的"),
  6. )
  7. is_private = models.BooleanField(choices=IS_PRIVATE_CHOICES)
  8. search_fields = Page.search_fields + [
  9. # 对人类可读的字符串进行索引,以进行搜索
  10. index.SearchField('get_is_private_display'),
  11. # 对逻辑值进行索引,以进行过滤
  12. index.FilterField('is_private'),
  13. ]

可调用属性还提供到一种对相关模型字段的索引方法(Callables also provide a way to index fields from related models)。在内联面板与模型集群的示例中,就是通过相关链接的标题,来对各个BookPage进行索引的。

  1. class BookPage(Page):
  2. # ...
  3. def get_related_link_titles(self):
  4. # 获取到标题清单,并将他们级联起来
  5. return '\n'.join(self.related_links.all().values_list('name', flat=True))
  6. search_fields = Page.search_fields + [
  7. # ...
  8. index.SearchField('get_realted_link_titles'),
  9. ]

对定制模型进行索引

所有Django模型,都可以被索引与搜索。

要实现这一点,就要从index.Indexed进行继承,并将一些search_fields加入到该模型。

  1. from wagtail.search import index
  2. class Book(index.Indexed, models.Model):
  3. title = models.CharField(max_length=255)
  4. genre = models.CharField(max_length=255, choices=GENRE_CHOICES)
  5. author = models.ForeignKey(Author, on_delete=models.CASCADE)
  6. published_date = models.DateTimeField()
  7. search_fields = [
  8. index.SearchField('title', partial_match=True, boost=10),
  9. index.SearchField('get_genre_display'),
  10. index.FilterField('genre'),
  11. index.FilterField('author'),
  12. index.FilterField('published_date'),
  13. ]
  14. # 因为此模型在其QuerySet中并没有一个搜索方法,因此就必须直接在后端调用搜索
  15. >>> from wagtail.search.backends import get_search_backend
  16. >>> s = get_search_backend()
  17. # 运行一次对 Roald Dohl 所写的书的搜索
  18. >>> roald_dahl = Author.objects.get(name="Roald Dahl")
  19. >>> s.search("chocolate factory", Book.objects.filter(author=roald_dahl))
  20. [<Book: Charlie and the chocolate factory>]