为了按照相关性来排序,需要将相关性表示为一个数值。在Elasticsearch中,相关性得分由一个浮点数进行表示,并在搜索结果中通过_source参数返回,默认排序是_source 降序。
有时,相关性评分对你来说并没有意义。例如,下面的查询返回所有user_id字段包含1 的结果:
GET /_search{"query" : {"bool" : {"filter" : {"term" : {"user_id" : 1}}}}}
这里没有一个有意义的分数:因为我们使用的是filter(过滤),这表明我们只希望获取匹配user_id:1的文档,并没有试图确定这些文档的相关性。实际上文档将按照随机顺序返回,并且每个文档都会评为零分。
NOTE
如果评分为0 对你造成了困扰,你可以使用 constant_score查询进行替代:
GET /_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"user_id" : 1
}
}
}
}
}
这将让所有文档应用一个恒定分数(默认为1)。他将执行与前述查询相同的查询,并且所有的文档像之前一样随即返回,这些文档只是有了一个分数而不是零分。
按照字段的值排序
在这个案例中,通过时间来对tweets 进行排序是有意义的,最新的tweets 排在最前。我们可以使用sort 参数进行实现:
GET /_search
{
"query" : {
"bool" : {
"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, //1
"_source" : {
"date": "2014-09-24",
...
},
"sort" : [ 1411516800000 ] //2
},
...
}
- _source不被计算,因为他并没有用于排序
- date 字段的值表示为自epoch(January 1,1970 00:00:00 UTC)以来的毫秒数,通过sort字段的值进行返回。
首先我们在每个结果中有一个新的名为sort 的元素,它包含了我们用于排序的值。在这个案例中,我们按照date 进行排序,在内部被索引为 自poch 以来的毫秒数 。 long 类型数 1411516800000 等价于日期字符串 2014-09-24 00:00:00 UTC
其次_score 和max_score 字段都是null。计算_sorce 的花销巨大,通常仅用于排序;我们并不根据相关性排序,所以记录_score 是没有意义的。如果无论如何你都要计算_sorce,你可以将track_scores 参数设置为true。
TIP
一个简便方法是,你可以指定一个字段用来排序
"sort": "number_of_children"
字段将会默认升序排序,而按照_score 的值进行降序排序。
多级排序
假定我们想要结合使用date 和 _score 进行查询,并且匹配的结果首先按照日期排序,然后按照相关性排序:
GET /_search
{
"query" : {
"bool" : {
"must": { "match": { "tweet": "manage text search" }},
"filter" : { "term" : { "user_id" : 2 }}
}
},
"sort": [
{ "date": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
}
排序条件的顺序是很重要的。结果首先按第一个条件排序,仅当结果集的第一个sort 值完全相同时才会按照第二个条件进行排序,以此类推。
多级排序并不一定包含_score 。你可以根据一些不同的字段进行排序,如地理距离或是脚本计算的特定值。
NOTE
Query-string 搜索也支持自定义排序,可以在查询字符串中使用sort 参数:
GET /_search?sort=date:desc&sort=_score&q=search
多值字段的排序
一种情形是字段有多个值的排序,需要记住这些值并没有固定的顺序;一个多值的字段仅仅是多个值的包装,这时应该选择哪个进行排序呢?
对于数字或日期,你可以将多值字段减为单值,这可以通过使用min、max、avg或是sum排序模式。例如你可以按照每个date 字段中最早日期进行排序,通过以下方法:
"sort": {
"dates": {
"order": "asc",
"mode": "min"
}
}
