作者:巧干篆书_618 | 来源:互联网 | 2024-12-11 11:35
本文深入探讨了Elasticsearch中的排序功能,包括相关性排序、字段值排序、多级排序及字符串和多值字段的排序策略,旨在帮助读者更好地理解和优化搜索结果。
相关性排序
Elasticsearch 默认根据文档与查询的相关性进行排序,相关性得分越高,文档排名越靠前。本文将详细介绍相关性概念及其计算方法,同时探讨如何利用 sort
参数优化查询结果。
排序方式
为了实现基于相关性的排序,Elasticsearch 使用 _score
字段表示每个文档的相关性得分,这是一个浮点数值。默认情况下,查询结果按照 _score
降序排列。然而,并非所有查询都能产生有意义的相关性得分。例如,过滤查询不会影响 _score
的计算,所有文档的相关性得分默认为1,表明它们的相关性相同。
字段值排序
对于基于特定字段值的排序,如时间戳,Elasticsearch 支持通过 sort
参数指定排序字段及其顺序。例如,为了获取最新文档,可以使用以下查询:
GET /_search
{
"query": {
"bool": {
"filter": [{ "term": { "user_id": 1 } }]
}
},
"sort": [{ "date": { "order": "desc" } }]
}
此查询首先过滤出 user_id
为1的文档,然后按 date
字段降序排列。注意,此时 _score
字段不再用于排序,因此不会计算相关性得分。
默认排序
如果只需按某个字段排序,可以直接指定字段名,例如:
"sort": "number_of_children"
默认情况下,字段值按升序排列,而 _score
则按降序排列。
多级排序
在多级排序中,可以结合多个字段进行排序。例如,先按日期排序,再按相关性得分排序:
GET /_search
{
"query": {
"bool": {
"must": [{ "match": { "tweet": "manage text search" } }],
"filter": [{ "term": { "user_id": 2 } }]
}
},
"sort": [
{ "date": { "order": "desc" } },
{ "_score": { "order": "desc" } }
]
}
多级排序首先按第一个字段排序,如果存在相同的值,则按第二个字段继续排序,依此类推。
字符串参数排序
在URL中使用 sort
参数也可以实现排序,例如:
GET /_search?sort=date:desc&sort=_score&q=search
多值字段排序
对于多值字段,Elasticsearch 允许选择特定的值进行排序,例如使用 min
、max
、avg
或 sum
模式。例如,按最早日期排序:
"sort": {
"dates": {
"order": "asc",
"mode": "min"
}
}
多值字段字符串排序
对于分析过的字符串字段,直接排序可能无法达到预期效果。建议使用 not_analyzed
子字段进行排序,确保字段值保持原样。例如,修改字段映射:
"tweet": {
"type": "text",
"analyzer": "english",
"fields": {
"raw": {
"type": "keyword"
}
}
}
这样,tweet
字段可用于全文搜索,而 tweet.raw
子字段则用于排序。
相关性简介
相关性评分 _score
是一个反映文档与查询相关程度的浮点数。Elasticsearch 使用 TF/IDF(Term Frequency/Inverse Document Frequency)算法计算相关性,主要包括:
检索词频率(TF)
检索词在文档中出现的频率越高,相关性越高。
反向文档频率(IDF)
检索词在索引中出现的频率越低,相关性越高。
字段长度准则
字段长度越短,相关性越高。
通过调整这些参数,可以优化查询结果的相关性。
理解评分标准
使用 explain
参数可以帮助理解查询结果的评分依据。例如:
GET /_search?explain=true
{
"query": {
"match": {
"tweet": "honeymoon"
}
}
}
explain
输出详细说明了评分的计算过程,有助于调试复杂的查询。
Explain API
文档匹配原因
通过 /index/type/id/_explain
路径,可以查看特定文档为何匹配或不匹配查询。例如:
GET /us/tweet/12/_explain
{
"query": {
"bool": {
"filter": [{ "term": { "user_id": 2 } }],
"must": [{ "match": { "tweet": "honeymoon" } }]
}
}
}
输出结果将详细解释文档匹配的原因。
数据字段
在排序时,Elasticsearch 需要快速访问文档的字段值,为此,它将字段值加载到内存中,形成“数据字段”。这一机制提高了排序和聚合操作的性能,但也增加了内存消耗。如果内存不足,可以通过增加节点来扩展集群。