- Search 执行的时候实际分两个步骤运作的
- Query 阶段
- Fetch 阶段 - Query-Then-Fetch
Query阶段
Fetch阶段
相关性算分问题
- 相关性算分在shard与shard间是相互独立的,也就意味着同一个term的IDF值在不同shard上是不同的。文档的相关性算分和他所处的shard相关
- 在文档数量不多是,会导致相关性算分严重不准的情况发生
- 解决思路有两个:
- 一是设置分片数为1个,从根本上排除问题,在问当数量不多的时候可以考虑该方案,比如百万到千万级别的文档数量
- 二是使用 DFS Query-then-Fetch 查询方式
- DFS Query-then-Fetch 是在拿到所有文档后再重现完整的计算一次相关性算分,耗费更多的cpu和内存,执行新能底下,一般不建议使用。使用方式如下:
排序
- es 默认会采用相关性算分排序,用户可以设定sorting 参数来自行设定排序规则
- 按照字符串排序比较特殊,因为es 有 text和keyword 两种类型,针对text类型排序,如下所示:
- 针对 keyword类型排序,可以返回预期结果
- 排序的过程实质是对字段原始内容排序的过程,这个过程中倒排索引无法发挥作用,需要用到正排索引,也是通过文档Id和字段可以快速得到字段原始内容。
- es对此提供了3种实现方式:
- fielddata 默认禁用
- doc values 默认启用,除了 text 类型
Fielddata vs DocValues
Fielddata
- Fielddata 默认是关闭的,可以通过如下api开启
- 此时字符串是按照分词后的term排序,往往结果很难复合预期
- 一般是在对分词做聚合分析的时候开启
Doc Values
- Doc Values 默认是启用的,可以在创建索引的时候关闭:
- 如果后面要再开启 doc values,需要做 reindex 操作 - 可以通过该字段获取 fielddata 或者 doc values 中存储的内容