为了按照相关性来排序,需要将相关性表示为一个数值。在Elasticsearch中,相关性得分由一个浮点数进行表示,并在搜索结果中通过_source参数返回,默认排序是_source 降序。

有时,相关性评分对你来说并没有意义。例如,下面的查询返回所有user_id字段包含1 的结果:

  1. GET /_search
  2. {
  3. "query" : {
  4. "bool" : {
  5. "filter" : {
  6. "term" : {
  7. "user_id" : 1
  8. }
  9. }
  10. }
  11. }
  12. }

这里没有一个有意义的分数:因为我们使用的是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
    },
    ...
}
  1. _source不被计算,因为他并没有用于排序
  2. 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"
    }
}