当我们 索引 一个文档,它的全文域被分析成词条以用来创建倒排索引。 但是,当我们在全文域 搜索 的时候,我们需要将查询字符串通过 相同的分析过程 ,以保证我们搜索的词条格式与索引中的词条格式一致。
全文查询,理解每个域是如何定义的,因此它们可以做 正确的事:
现在你可以理解在 开始章节 的查询为什么返回那样的结果:
date
域包含一个精确值:单独的词条 `2014-09-15`。_all
域是一个全文域,所以分词进程将日期转化为三个词条: `2014`, `09`, 和 `15`。
当我们在 _all
域查询 2014`,它匹配所有的12条推文,因为它们都含有 `2014
:
GET /_search?q=2014 # 12 results
当我们在 _all
域查询 2014-09-15`,它首先分析查询字符串,产生匹配 `2014`, `09`, 或 `15
中 任意 词条的查询。这也会匹配所有12条推文,因为它们都含有 2014
:
GET /_search?q=2014-09-15 # 12 results !
当我们在 date
域查询 `2014-09-15`,它寻找 精确 日期,只找到一个推文:
GET /_search?q=date:2014-09-15 # 1 result
当我们在 date
域查询 `2014`,它找不到任何文档,因为没有文档含有这个精确日志:
GET /_search?q=date:2014 # 0 results !
有些时候很难理解分词的过程和实际被存储到索引中的词条,特别是你刚接触 Elasticsearch。为了理解发生了什么,你可以使用 analyze
API 来看文本是如何被分析的。在消息体里,指定分析器和要分析的文本:
GET /_analyze { "analyzer": "standard", "text": "Text to analyze" }
结果中每个元素代表一个单独的词条:
{ "tokens": [ { "token": "text", "start_offset": 0, "end_offset": 4, "type": "<ALPHANUM>", "position": 1 }, { "token": "to", "start_offset": 5, "end_offset": 7, "type": "<ALPHANUM>", "position": 2 }, { "token": "analyze", "start_offset": 8, "end_offset": 15, "type": "<ALPHANUM>", "position": 3 } ] }
token
是实际存储到索引中的词条。 position
指明词条在原始文本中出现的位置。 start_offset
和 end_offset
指明字符在原始字符串中的位置。

每个分析器的 type
值都不一样,可以忽略它们。它们在Elasticsearch中的唯一作用在于keep_types
token 过滤器。
analyze
API 是一个有用的工具,它有助于我们理解Elasticsearch索引内部发生了什么,随着深入,我们会进一步讨论它。
指定分析器
当Elasticsearch在你的文档中检测到一个新的字符串域 ,它会自动设置其为一个全文 字符串
域,使用 标准
分析器对它进行分析。
你不希望总是这样。可能你想使用一个不同的分析器,适用于你的数据使用的语言。有时候你想要一个字符串域就是一个字符串域--不使用分析,直接索引你传入的精确值,例如用户ID或者一个内部的状态域或标签。
要做到这一点,我们必须手动指定这些域的映射。