分析控制

查询只能查找在倒排索引中出现的词,所以确保在文档索引的时候以及字符串查询的时候使用同一个分析器是很重要的,为了查询的词能够在倒排索引中匹配到。

尽管我们说文档中每个字段的分析器是已经定好的。但是字段可以有不同的分析器,通过给那个字段配置一个指定的分析器或者直接使用类型,索引,或节点上的默认分析器。在索引的时候,一个字段的值会被配置的或者默认的分析器分析。

举个例子,让我们添加一个字段到my_index

PUT /my_index/_mapping/my_type
{
    "my_type": {
        "properties": {
            "english_title": {
                "type":     "string",
                "analyzer": "english"
            }
        }
    }
}

现在我们可以通过analyzeAPI分析Foxes词来比较english_title字段中的值以及title字段中的值在创建索引的时候是怎么被分析的:

GET /my_index/_analyze?field=my_type.title   <1>
Foxes
GET /my_index/_analyze?field=my_type.english_title <2>
Foxes
  • <1> 使用standard分析器的title字段将会返回词foxes
  • <2> 使用english分析器的english_title字段将会返回词fox

这意味着,如果我们为精确的词fox执行一个低级别的term查询,english_title字段会匹配而title字段不会。

match查询一样的高级别的查询可以知道字段的映射并且能够在被查询的字段上使用正确的分析器。我们可以在validate-query API的执行中看到这个:

GET /my_index/my_type/_validate/query?explain
{
    "query": {
        "bool": {
            "should": [
                { "match": { "title":         "Foxes"}},
                { "match": { "english_title": "Foxes"}}
            ]
        }
    }
}

它会返回explanation

(title:foxes english_title:fox)

match查询为每个字段使用合适的分析器用来确保在那个字段上可以用正确的格式查询这个词。

默认分析器

虽然我们可以在字段级别指定一个分析器,但是如果我们在字段级别没有指定分析器的话,那要怎么决定某个字段使用什么分析器呢?

分析器可以在好几个地方设置。Elasticsearch会查找每个级别直到找到它可以使用的分析器。在创建索引的时候,Elasticsearch查找分析器的顺序如下:

  • 在映射文件中指定字段的analyzer,或者
  • 在文档的_analyzer字段上指定分析器,或者
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置默认分析器default
  • standard分析器

查找索引的时候,Elasticsearch查找分析器的顺序稍微有点不一样:

  • 在查询参数中指定analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置默认分析器default
  • standard分析器

提示:

上面列表中用斜体字的两行突出了创建索引以及查询索引的时候Elasticsearch查找分析器的区别。_analyzer字段允许你为每个文档指定默认的分析器(比如, english, french, spanish),虽然在查询的时候指定analyzer参数,但是在一个索引中处理多种语言这并不是一个好方法,因为在多语言环境下很多问题会暴露出来。

有时候,在创建索引与查询索引的时候使用不同的分析器也是有意义的。举个例子:在创建索引的时候想要索引同义词 (比如, 出现quick的时候,我们也索引 fast, rapid, 和 speedy)。但是在查询索引的时候,我们不需要查询所有的同义词,我们只要查询用户输入的一个单词就可以了,它可以是quick, fast, rapid, 或者 speedy

为了满足这种差异,Elasticsearch也支持index_analyzersearch_analyzer 参数,并且分析器被命名为default_indexdefault_search

把这些额外的参数考虑进去,Elasticsearch查找所有的分析器的顺序实际上像下面的样子:

  • 在映射文件中指定字段的index_analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在文档的_analyzer字段上指定分析器,或者
  • 在映射文件中指定类型的创建索引的默认分析器index_analyzer
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置创建索引的默认分析器default_index
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置创建索引的默认分析器default_index
  • 在节点级别设置默认分析器default
  • standard分析器

以及查询索引的时候:

  • 在查询参数中指定analyzer,或者
  • 在映射文件中指定字段的search_analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在映射文件中指定类型的查询索引的默认分析器analyzer
  • 在索引映射文件中设置查询索引的默认分析器default_search
  • 在索引映射文件中设置默认分析器default_search
  • 在节点级别设置查询索引的默认分析器default_search
  • 在节点级别设置默认分析器default
  • standard 分析器

实际配置分析器

可以指定分析器的地方实在是太多了,但实际上,指定分析器很简单。

用索引配置,而不是用配置文件

第一点要记住的是,尽管你开始使用Elasticsearch仅仅只是为了一个简单的目的或者是一个应用比如日志,但很可能你会发现更多的案例(use cases翻译成案例不知道合不合适,如果有更好的用词,请联系我,Tks),结局是在同一个集群中运行着好几个不同的应用。每一个索引都需要是独立的,并且可以被独立的配置。你不要想着给一个案例设置默认值,但是不得不重写他们来适配后面的案例。

这个规则把节点级别的配置分析器方法排除在外了。另外,节点级别的分析器配置方法需要改变每个节点的配置文件并且重启每个节点,这将成为维护的噩梦。保持Elasticsearch持续运行并通过API来管理索引的设置是一个更好的方法。

保持简便性

大多数时间,你可以预先知道文档会包含哪些字段。最简单的方法是在你创建索引或者添加类型映射的时候为每一个全文检索字段设置分析器。虽然这个方法有点啰嗦,但是它可以很容易的看到哪个字段应用了哪个分析器。

通常情况下,大部分的字符串字段是确切值not_analyzed字段(索引但不分析字段)比如标签,枚举,加上少数全文检索字段会使用默认的分析器,像standard 或者 english 或者其他语言。然后你可能只有一到两个字段需要定制分析:或许title字段需要按照你查找的方式去索引来支持你的查找。(指的是你查找的字符串用什么分析器,创建索引就用什么分析器)

你可以在索引设置default分析器的地方为几乎所有全文检索字段设置成你想要的分析器,并且只要在一到两个字段指定专门的分析器。如果,在你的模型中,你每个类型都需要不同的分析器,那么在类型级别使用analyzer配置来代替。

提示:

一个普通的像日志一样的基于时间轴的工作流数据每天都得创建新的索引,忙着不断的创建索引。虽然这种工作流阻止你预先创建索引,但是你可以使用索引模板来指定新的索引的配置和映射。

下一节:在我们去讨论多字段检索中的更复杂的查询前,让我们顺便先解释一下为什么我们只用一个主分片来创建索引。