ElasticSearch学习笔记之十九 多字段排序和字符串排序
- 排序
- 多级排序
- 字符串排序
排序
为了按照相关性来排序,需要将相关性表示为一个数值。在 Elasticsearch 中, 相关性得分 由一个浮点数进行表示,并在搜索结果中通过 _score
参数返回, 默认排序是 _score
降序。
新建索引映射
PUT tweet
{
"mappings": {
"tweet": {
"properties": {
"about": {
"type": "text"
},
"comments": {
"type": "nested",
"properties": {
"content": {
"type": "text"
},
"date": {
"type": "date"
},
"user_id": {
"type": "long"
}
}
},
"date": {
"type": "date"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"topic": {
"type": "text"
},
"tweet": {
"type": "text"
},
"user_id": {
"type": "long"
}
}
}
}
}
插入数据
PUT tweet/tweet/1
{
"tweet": "What is Elasticsearch?",
"date": "2014-09-14",
"name": "Mary Jones",
"about":["es","elasticsearch"],
"topic":"elasticsearch",
"user_id": 1,
"comments": [
{
"content": "very good",
"date": "2014-09-14",
"user_id": 1
},
{
"content": "good question",
"date": "2014-09-15",
"user_id": 2
}
]
}
PUT tweet/tweet/2
{
"tweet": "How can we study Elasticsearch?",
"date": "2014-09-18",
"name": "Mary Jones",
"about":["es","elasticsearch"],
"topic":"elasticsearch",
"user_id": 1,
"comments": [
{
"content": "very good",
"date": "2014-09-18",
"user_id": 1
},
{
"content": "good question",
"date": "2014-10-15",
"user_id": 2
}
]
}
PUT tweet/tweet/3
{
"tweet": "How can we manage Elasticsearch?",
"date": "2014-10-18",
"name": "Tom Foxs",
"about":["es","elasticsearch"],
"topic":"elasticsearch",
"user_id": 2,
"comments": [
{
"content": "do not know",
"date": "2014-09-14",
"user_id": 3
},
{
"content": "good question",
"date": "2014-09-15",
"user_id": 2
}
]
}
此时假设我们希望看到按照时间的排序,来查询数据
GET tweet/tweet/_search
{
"sort": [
{
"date": {
"order": "desc"
}
}
]
}
结果如下:
- 文档返回时多出来了
sort
它包含了我们用于排序的值。 -
_score
不被计算, 因为它并没有用于排序。 -
date
字段的值表示为自epoch (January 1, 1970 00:00:00 UTC)
以来的毫秒数,通过sort
字段的值进行返回。
_score
和 max_score
字段都是 null 。计算 _score
的花销巨大,通常仅用于排序;这里 我们并不根据相关性排序,所以记录 _score
是没有意义的。如果无论如何你都要计算 _score
, 你可以将 track_scores
参数设置为 true
。
相关性查询
GET tweet/tweet/_search
{
"query": {
"match": {
"name": "jones"
}
}
}
查询结果如下:
多级排序
假定我们想要结合使用 date
和 _score
进行查询,并且匹配的结果首先按照日期排序,然后按照相关性排序:
GET tweet/tweet/_search
{
"query": {
"match": {
"name": "jones"
}
},
"sort": [
{
"date": {
"order": "desc"
}
},
{
"_score":{
"order": "desc"
}
}
]
}
排序条件的顺序是很重要的。结果首先按第一个条件排序,仅当结果集的第一个 sort 值完全相同时才会按照第二个条件进行排序,以此类推。
字符串排序
以全文 analyzed 字段排序会消耗大量的内存。
如果你想分析一个字符串,如 fine old art
, 这包含 3 项。我们很可能想要按第一项的字母排序,然后按第二项的字母排序,诸如此类,但是 Elasticsearch 在排序过程中没有这样的信息。
你可以使用 min
和 max
排序模式(默认是 min
),但是这会导致排序以 art
或是 old
,任何一个都不是所希望的。
为了以字符串字段进行排序,这个字段应仅包含一项: 整个 not_analyzed
字符串。 但是我们仍需要 analyzed
字段,这样才能以全文进行查询
一个简单的方法是用两种方式对同一个字符串进行索引,这将在文档中包括两个字段: analyzed
用于搜索, not_analyzed
用于排序
但是保存相同的字符串两次在 source
字段是浪费空间的。 我们真正想要做的是传递一个 _单字段 但是却用两种方式索引它。所有的 _core_field
类型 (strings, numbers, Booleans, dates)
接收一个 fields 参数
该参数允许你转化一个简单的映射如我们上面为名字创建的映射:
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
对应检索
GET tweet/tweet/_search
{
"query": {
"match": {
"name": "jones"
}
},
"sort": [
{
"name.keyword": {
"order": "asc"
}
},
{
"_score":{
"order": "desc"
}
}
]
}