elasticsearch之sorting and relevance
来源:互联网 发布:冯伟文是谁 知乎 编辑:程序博客网 时间:2024/06/10 07:43
默认情况下,es中的返回结果是根据relevance排序的,相关性最强的结果在最前边。接下来我们会介绍相关性是什么意思,是如何计算的?但是,我们先把焦点放在sort这个参数上,看看如何使用
1:sorting
为了能按照相关性排序,我们需要用一个数值来代表相关性。在es中,_score字段就是表示相关性的数字,用浮点类型表示,默认情况系按照_score的降序排列。
有些情况下,我们并没有一个有意义的相关性数值。比如:下边的query只是要返回user_id为1的doc:
GET /_search{ "query" : { "filtered" : { "filter" : { "term" : { "user_id" : 1 } } } }}
filter并不需要计算相关性,因此也不需要计算_score,另外match_all这种类型的查询把_score值都设置成为1,也就是说把所有doc的相关性都认为是一样的。
sorting by field value:
下边这个例子中,根据时效性排序可能是有意义的,最新的记录放在最前边。我们可以用sort这个参数来实现:
GET /_search{ "query" : { "filtered" : { "filter" : { "term" : { "user_id" : 1 }} } }, "sort": { "date": { "order": "desc" }}}在返回结果中,你会发现有些不同:
"hits" : { "total" : 6, "max_score" : null, (1) "hits" : [ { "_index" : "us", "_type" : "tweet", "_id" : "14", "_score" : null, (2) "_source" : { "date": "2014-09-24", ... }, "sort" : [ 1411516800000 ] (3) }, ...}(1)(2)_score并没有被计算,因为不用它来进行排序
(3)返回结果中有了sort值,是date的字段的milliseconds
可以看到:在没一行返回结果中,没一条记录都有了一个元素叫做sort,包含了用来排序的字段的值;_score和max_score都是null。计算score是一个昂贵的操作,而我们这里并不像用score来进行排序,因此我们并不需要对score进行计算,如果无论如何都想要计算score值,我们可以设置track_socres为true。
multilevel sorting:
多个排序标准,比如先按照date排序再按照score排序:
GET /_search{ "query" : { "filtered" : { "query": { "match": { "tweet": "manage text search" }}, "filter" : { "term" : { "user_id" : 2 }} } }, "sort": [ { "date": { "order": "desc" }}, { "_score": { "order": "desc" }} ]}注意顺序是很重要的,结果首先按照第一个标准排序,依次类推。
多重标准的排序并不一定要仿照上边的例子一样绑定_score,完全可以任意指定字段,也可以用自定义的字段用脚本计算。
query_string也支持sort:
GET /_search?sort=date:desc&sort=_score&q=search
sorting on multivalue fields:
如果对多值字段排序,请记住,这些值并没有内在的顺序。一个多值字段只是一系列数值的集合,我们应该选择哪一个数值进行排序呢?
对于数值类型和日期类型,我们可以选择max/min/avg/sum等作为排序标准。例如:可以对date字段排序,运用每一个doc中date多值中的最早的时间最为排序标准。
"sort": { "dates": { "order": "asc", "mode": "min" }}
2:string sorting and multifields
analyzed的string field通常都是多值的,但是在这些field上进行的排序操作多半不是我们想要的结果。比如我们一个field经过analyzed后成为3个term:fine old art,我们期望先按照第一个term排序,再按照第二个,依次类推。但是es在排序的过程中并没有对这些信息的处理。你可以用min max等制定排序模式,但是也只是选定了 old或者 art作为了排序依据。
因此,如果想要对一个string field进行排序,那么这个field必须只含有一个term,但是大多数string field是包含多个term的。那么问题来了,是不是想起了multi field的呢?是的,就是这么干的,主属性用analyzed,副属性用not_analyzed作为排序的字段。
注意:如果真要对一个analyzed string field进行排序,会消耗很多内存,请参见后续的FieldData环节。
3:what is relevance?
这个就是tf/idf,之前博客有介绍过。主要考量三个因素:term frequence,inverse document frequence,field-length norm。
如果想要对一个复杂的query进行debug,弄清楚_score计算的每一个细节是比较困难的。es也提供了explain参数来查看score计算的某些参数值:
"_explanation": { "description": "weight(tweet:honeymoon in 0) [PerFieldSimilarity], result of:", "value": 0.076713204, "details": [ { "description": "fieldWeight in 0, product of:", "value": 0.076713204, "details": [ { "description": "tf(freq=1.0), with freq of:", "value": 1, "details": [ { "description": "termFreq=1.0", "value": 1 } ] }, { "description": "idf(docFreq=1, maxDocs=1)", "value": 0.30685282 }, { "description": "fieldNorm(doc=0)", "value": 0.25, } ] } ]}注意,explain操作是非常昂贵的操作,在生产环境中尽量不要使用,只是作为debug比较好。
explain的输出是对每一条结果的一个解释,同时我们可以用explain api来查看某一条为什么被match到了?为什么没有被match到。
GET /us/tweet/12/_explain{ "query" : { "filtered" : { "filter" : { "term" : { "user_id" : 2 }}, "query" : { "match" : { "tweet" : "honeymoon" }} } }}
除了前边的信息,我们会发现有这么一条输出:
"failure to match filter: cache(user_id:[2 TO 2])"
也就是说,是used_id字段使得这行记录没有被match到!
4:fielddata
当我们要对一个field进行排序的时候,es需要访问到match到的doc中这个field的值。对倒排索引来说,search的性能是非常好的,但是这种结构不适合sort操作。当search的时候,我们是把一个term对应到一系列的docs,而当sort的时候,我们是要把一个doc对应到terms,也就是说我们是“uninvert”这个inverted index。
为了能够使得sort操作更为高效,es把对应field的所有值都加载到内存中,也就是我们说的fielddata。
注意:es不仅仅把对应query所match到的document的值加载到内存,而是把索引的所有document加载到内存,并不去区分type。
es这样做的原因是:从磁盘中去uninvert倒排索引太慢了。即使你当前的request只是需要一部分docs,你可以在下一个request会访问其余的docs,所以直接一次把所有doc都加载到内存中。
fielddata在许多场景下都有应用:
对指定字段排序
对指定字段aggregation
某些特定的filter(比如geolocation filters)
对一些field执行script操作
等等。
显然,这回消耗掉很大的内存,尤其是对基数很高的string类型的field,这些field包含许多不同的term,比如email的内容。幸运的是,内存不足可以用水平扩展来解决,在集群中增加更多的节点。
截至到目前,我们应该了解到fielddata是什么?意识到fielddata会消耗到大量的内存。之后,我们会接触到如何决定fielddata消耗内存的大小,如何限制可用内存的数量以及如何提前加载fielddata来提升用户体验。
- elasticsearch之sorting and relevance
- elasticsearch---search in depth之controlling relevance
- ES权威指南_01_get start_08 Sorting and Relevance
- Elasticsearch之Nested Sorting
- elasticsearch 代码分析之modules and services
- Elasticsearch的DSL之 term and match
- Elasticsearch的DSL之query and filter
- Restricting And Sorting Data
- Sorting and Searching
- CListCtrl and sorting rows
- Shifting and Sorting Matrices
- Searching and Sorting
- Searching and Sorting
- Searching and Sorting
- Searching and Sorting
- Restricting and Sorting Data
- 知识点总结2 External Sorting, Bucket Sorting, and Radix Sorting
- Java操作ElasticSearch之Update数据 and Java操作ElasticSearch之Delete数据
- CodeForces#286 div.2 题解
- 华为机试—约瑟夫环替换计数器m(循环链表解决)
- hdu 1402 A * B Problem Plus (FFT + 大数相乘)
- 企业级数据结构-栈的链式存储设计与实现
- 语音编解码
- elasticsearch之sorting and relevance
- Oracle性能分析:开启SQL跟踪和获取trace文件|trace文件解读
- Windows 结构化异常与 C / C++异常的一些事
- Ubuntu的最新信息
- Android实现下拉导航选择菜单效果
- AndroidWear官方文档总结06 - 添加多页面到通知
- Activity被销毁重建后Fragment的处理
- iOS7 TableView适配
- 一篇不错的v4l2