elasticsearnch排序
一. 相关性排序
查询语句中,结果集会按照_score降序排列;
过滤语句与_score没有关系,包含隐含的match_all条件,所有的_score默认为1;
使用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, <1>
        "_source" :     {
             "date":    "2014-09-24",
             ...
        },
        "sort" :        [ 1411516800000 ] <2>
    },
    ...
}
可以发现:
- _score 字段没有经过计算,因为它没有用作排序
- date 字段被转为毫秒当作排序依据
在每个结果中增加了sort字段,内容为date转为毫秒的结果;
_score和max_score的内容都为Null;
计算_score比较耗时,如果不指定用相关性排序,不需要统计相关性,如果强制指定需要track_scores设置为true
指定多个排序,比如先按照date,再按照_score
GET /_search
{
    "query" : {
        "filtered" : {
            "query":   { "match": { "tweet": "manage text search" }},
            "filter" : { "term" : { "user_id" : 2 }}
        }
    },
    "sort": [
        { "date":   { "order": "desc" }},
        { "_score": { "order": "desc" }}
    ]
}
字符串查询指定排序
GET /_search?sort=date:desc&sort=_score&q=search
多值字段本身是一个集合,本身无法排序,需要取出一项内容,比如可以用min, max, avg 或 sum这些模式
"sort": {
    "dates": {
        "order": "asc",
        "mode":  "min"
    }
}
二. 字符串排序
被analyser处理过的字符串称为,analyzed field,analyzed字符串字段同时也是多值字段;
使用字符串排序,必须包含完整的not_analyzed字符串,进行全文搜索的时候还要使用analyzed field;
可以同一个字段包含两种索引方式,只要改变index的mapping即可
原有的mapping
"tweet": {
    "type":     "string",
    "analyzer": "english"
}
修改后的mapping
"tweet": { <1>
    "type":     "string",
    "analyzer": "english",
    "fields": {
        "raw": { <2>
            "type":  "string",
            "index": "not_analyzed"
        }
    }
}
tweet 字段用于全文本的 analyzed 索引方式不变
新增的 tweet.raw 子字段索引方式是 not_analyzed
现在,在给数据重建索引后,我们既可以使用 tweet 字段进行全文本搜索,也可以用tweet.raw字段进行排序
GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    },
    "sort": "tweet.raw"
}
对于analyzed强制排序会消耗大量内存
三. 相关性
相关性取决于查询类型
fuzzy 查询会计算与关键词的拼写相似程度
terms查询会计算 找到的内容与关键词组成部分匹配的百分比
一般意义上我们说的全文本搜索是指计算内容与关键词的类似程度
ElasticSearch的相似度算法被定义为 TF/IDF,即检索词频率/反向文档频率
内容包括:
- 检索词频率:
- 反向文档频率:在越多的文档中出现,相关性越低,即普遍性;
- 字段长度准则:出现在段字段比在长字段相关性高
理解评分标准
explain参数设置为true,得到详细信息
GET /_search?explain <1>
{
   "query"   : { "match" : { "tweet" : "honeymoon" }}
}
explain 参数可以让返回结果添加一个 _score 评分的得来依据
普通查询返回的元数据
{
    "_index" :      "us",
    "_type" :       "tweet",
    "_id" :         "12",
    "_score" :      0.076713204,
    "_source" :     { ... trimmed ... },
}
加入文档来自哪个分片上的信息,词频率和 文档频率是在每个分片中计算出来的,而不是每个索引中
 	"_shard" :      1,
    "_node" :       "mzIVYCsqSWCG_M_ZffSs9Q",
返回的_explanation会返回其他详情
"_explanation": { <1>
   "description": "weight(tweet:honeymoon in 0)
                  [PerFieldSimilarity], result of:",
   "value":       0.076713204,
   "details": [
      {
         "description": "fieldWeight in 0, product of:",
         "value":       0.076713204,
         "details": [
            {  <2>
               "description": "tf(freq=1.0), with freq of:",
               "value":       1,
               "details": [
                  {
                     "description": "termFreq=1.0",
                     "value":       1
                  }
               ]
            },
            { <3>
               "description": "idf(docFreq=1, maxDocs=1)",
               "value":       0.30685282
            },
            { <4>
               "description": "fieldNorm(doc=0)",
               "value":        0.25,
            }
         ]
      }
   ]
}
- <1> honeymoon 相关性评分计算的总结
- <2> 检索词频率
- <3> 反向文档频率
- <4> 字段长度准则
第一部分是关于计算的总结。告诉了我们 "honeymoon" 在 tweet字段中的检索词频率/反向文档频率或 TF/IDF, (这里的文档 0 是一个内部的ID,跟我们没有关系,可以忽略。)
然后解释了计算的权重是如何计算出来的:
检索词频率:检索词 honeymoon 在 tweet 字段中的出现次数。
反向文档频率:检索词 honeymoon 在 tweet 字段在当前文档出现次数与索引中其他文档的出现总数的比率。
字段长度准则:文档中 tweet 字段内容的长度 -- 内容越长,值越小。
提示: JSON形式的explain描述是难以阅读的 但是转成 YAML 会好很多,只需要在参数中加上 format=yaml
Explain Api
explain加到某一文档上,它会告诉你为何这个文档会被匹配,以及一个文档为何没有被匹配。
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])"
四. 数据字段
- 当搜索的时候,我们需要用检索词去遍历所有的文档
- 当排序的时候,我们需要遍历文档中所有的值,我们需要做反倒序排列操作
 为了提高排序效率,ElasticSearch 会将所有字段的值加载到内存中,这就叫做"数据字段"
 ElasticSearch中的字段数据常被应用到以下场景:
- 对一个字段进行排序
- 对一个字段进行聚合
- 某些过滤,比如地理位置过滤
- 某些与字段相关的脚本计算
这样有可能会耗尽内存,这就需要横向扩展或者限制内存;
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号