同福

Elasticsearch使用script_score微调查询结果的文档的评分【20210715】

介绍

介绍

控制Elasticsearch搜索引擎的查询结果的评分的终极武器script_score,评分完全的自定义化,真的是想怎么玩就怎么玩,爽的不要不要的。

福哥今天会给大家讲讲如何使用ES的script_score去自定义查询结果的每个文档的评分,完完全全地按照自己的想法去设计文档的评分计算方法。

script_score

按照官方的说法,使用script_score可以通过Groovy脚本编写一个函数,用来计算文档的评分。在这个函数里面可以访问文档的全部字段以及文档的默认评分,甚至还可以访问词频和逆向文档频率(不过福哥没有找到示例)。

Groovy是一个用来给Java程序做单元测试的辅助脚本,它和JavaScript非常相似,大家可以很容易上手的。

公式计算评分

假设福哥给同福网的文章搜索设计一个自定义评分逻辑,将文章的访问量作为一个加权的考量,将访问量除以10000次的商作为增幅去扩大默认评分的值,计算公式如下:

_score * ((doc['mReadC'].value + 0.0) / 100 + 1)

应用到ES的query里,需要将script_score放到function_score里面,因为script_score是function_score的一种方式,具体到上面的例子就是这个样子的:

{
  "from": 0,
  "size": 10,
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "mTitle": {
                  "query": "java",
                  "minimum_should_match": "80%",
                  "boost": 6
                }
              }
            }
          ]
        }
      },
      "script_score": {
        "script": {
          "source": "_score * (doc['mReadC'].value / 10000 + 1)"
        }
      }
    }
  }
}

home/topic/2021/0715/17/542a708ece2f75389c503012c5a4f3ee.png

函数计算评分

函数计算和公式计算区别就是可以支持更为复杂的逻辑,福哥设计了一个简单的逻辑,如果加权超过2倍则无论加权是多少倍都按2倍计算,函数如下:

float readC = doc['mReadC'].value;
float readCRate = readC / 10000 + 1;
if (readCRate > 2) { 
    return _score * 2; 
} 
return _score * readCRate;

应用到ES的query里,需要将函数的换行符去掉,或者换成“\n”,因为JSON格式要求这样,具体的例子如下:

{
  "from": 0,
  "size": 10,
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "must": [
            {
              "terms": {
                "mStat": [
                  1
                ]
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "match": {
                      "mTitle": {
                        "query": "java",
                        "minimum_should_match": "80%",
                        "boost": 6
                      }
                    }
                  },
                  {
                    "match": {
                      "content": {
                        "query": "java",
                        "minimum_should_match": "100%",
                        "boost": 1
                      }
                    }
                  }
                ]
              }
            }
          ]
        }
      },
      "script_score": {
        "script": {
          "source": "float readC = doc['mReadC'].value; float readCRate = readC \/ 10000 + 1; if (readCRate > 2) { return _score * 2; } return _score * readCRate;"
        }
      }
    }
  }
}

home/topic/2021/0715/19/321fb2b94608dbc8a70b6bbbcf5f8bae.png

总结

今天福哥给童鞋们讲解了Elasticsearch的script_score的使用技巧,通过script_score可以完全地对查询结果里面的文档的评分进行自定义设计,这个可以帮助我们提高用户体验。