默认情况下,结果集会按照相关性进行排序 – 相关性越高,排名越靠前。
1. 字段值排序
下面例子中,对结果集按照时间排序,我们使用 sort 参数进行排序:
首先,在每个结果中增加了一个 sort 字段,它所包含的值是用来排序的。 在这个例子当中 date 字段在内部被转为毫秒, 即长整型数字 1411516800000 等同于日期字符串 2014-09-24 00:00:00 UTC 。
其次就是 _score 和 max_score 字段都为 null 。计算 _score 是比较消耗性能的, 而且通常主要用作排序 – 我们不是用相 关性进行排序的时候,就不需要统计其相关性。 如果你想强制计算其相关性,可以设置 track_scores 为 true 。
2. 默认排序
你可以只指定要排序的字段名称:
字段值默认以顺序排列,而 _score 默认以倒序排列。
3. 多级排序
如果我们想要合并一个查询语句,并且展示所有匹配的结果集使用第一排序是 date ,第二排序是 _score :
结果集会先用第一排序字段来排序,当用用作第一字段排序的值相同的时候, 然后再用第二字段对第一排 序值相同的文档进行排序,以此类推。
多级排序不需要包含 _score – 你可以使用几个不同的字段,如位置距离或者自定义数值。
4. 字符串参数排序
字符查询也支持自定义排序,在查询字符串使用 sort 参数就可以:
5. 为多值字段排序
在为一个字段的多个值进行排序的时候, 其实这些值本来是没有固定的排序的.
对于数字和日期,你可以从多个值中取出一个来进行排序,你可以使用 min , max , avg 或 sum 这些模式。
比说你可以在 dates 字段中用最早的日期来进行排序:
6. 多值字段字符串排序
analyzed 字符串字段同时也是多值字段,在这些字段上排序往往得不到你想要的值。 比如你分析一个字符 “fine old art” , 它最终会得到三个值。例如我们想要按照第一个词首字母排序, 如果第一个单词相同的话,再用第二个词的首字母排序,以 此类推,可惜 ElasticSearch 在进行排序时 是得不到这些信息的。
当然你可以使用 min 和 max 模式来排(默认使用的是 min 模式)但它是依据 art 或者 old 排序, 而不是我们所期望的 那样。
为了使一个string字段可以进行排序,它必须只包含一个词:即完整的 not_analyzed 字符串。 当然我们需要对字段进行全文 本搜索的时候还必须使用 analyzed 。
在 _source 下相同的字符串上排序两次会造成不必要的资源浪费。 而我们想要的是一个字段中同时包含这两种索引方式。 现在我们介绍一个在所有核心字段类型上通用的参数 fields ,这样我们就可以改变它的mapping:
改变前:
改变后的多值字段mapping如下:
现在,我们既可以使用 tweet 字段进行全文本搜索,也可以用 tweet.raw 字段进行排序:
警告: 对 analyzed 字段进行强制排序会消耗大量内存。 详情请查阅《字段类型简介》相关内容。
7. 数据字段
当你对一个字段进行排序时,ElasticSearch 需要进入每个匹配到的文档得到相关的值。 倒排索引在用于搜索时是非常卓越
的,但却不是理想的排序结构。
- 当搜索的时候,我们需要用检索词去遍历所有的文档。
- 当排序的时候,我们需要遍历文档中所有的值,我们需要做反倒序排列操作。
为了提高排序效率,ElasticSearch 会将所有字段的值加载到内存中,这就叫做"数据字段"。
重要: ElasticSearch将所有字段数据加载到内存中并不是匹配到的那部分数据。 而是索引下所有文档中的值,包括所
有类型。
将所有字段数据加载到内存中是因为从硬盘反向倒排索引是非常缓慢的。尽管你这次请求需要的是某些文档中的部分数据,
但你下个请求却需要另外的数据,所以将所有字段数据一次性加载到内存中是十分必要的。
ElasticSearch中的字段数据常被应用到以下场景:
- 对一个字段进行排序
- 对一个字段进行聚合
- 某些过滤,比如地理位置过滤
- 某些与字段相关的脚本计算
毫无疑问,这会消耗掉很多内存,尤其是大量的字符串数据 – string字段可能包含很多不同的值,比如邮件内容。 值得庆幸
的是,内存不足是可以通过横向扩展解决的,我们可以增加更多的节点到集群。