TypechoJoeTheme

IT技术分享

统计

04. ES文档评分查询——ElasticSearch搜索专栏

2022-06-13
/
0 评论
/
622 阅读
/
正在检测是否收录...
06/13

[TOC]

一、Constant Score查询

如果不想让检索词频率TF(Term Frequency)对搜索结果排序有影响

只想过滤某个文本字段是否包含某个词,可以使用Constant Score将查询语句包装起来。

使用filter和constant_score进行处理。

1.1 DSL方式

GET /hotel/_search
{
  "_source": ["amenities"],
  "query": {
   "constant_score": {    //满足条件即打分为1
      "filter": {
        "match": {        //查询设施中包含“停车场”的文档
          "amenities": "停车场"
        }
      }
    }
  }
}

在Constant Score搜索中,参数boost可以控制命中文档的得分,默认值为1.0

GET /hotel/_search
{
  "_source": ["amenities"],
  "query": {
    "constant_score": {
      "boost": 2.0,               //设置Constant Score查询命中文档的得分为2.0
      "filter": {
        "match": {
          "amenities": "停车场"
        }
      }
    }
  }
}

1.2 Java 客户端方式

在Java客户端上构建Constant Score搜索时,可以使用ConstantScoreQueryBuilder类的实例进行构建

public void constantScoreSearch() {
    //新建搜索请求
    SearchRequest searchRequest = new SearchRequest("hotel");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //构建设施包含“停车场”的constant score查询
    ConstantScoreQueryBuilder constantScoreQueryBuilder = new ConstantScoreQueryBuilder(
        QueryBuilders.termQuery("amenities", "停车场"));
    searchSourceBuilder.query(constantScoreQueryBuilder);
    constantScoreQueryBuilder.boost(2.0f);
    searchRequest.source(searchSourceBuilder);  //设置查询
   printResult(searchRequest);                  //打印结果
}

二、Function Score查询

当使用ES进行搜索时,命中的文档默认按照相关度进行排序。

有些场景下用户需要干预该“相关度”,此时就可以使用Function Score查询。

使用function_score进行查询可以让用户修改文档的评分。

要使用function_score进行查询,必须定义一个查询以及一个或多个函数,这些函数将为查询返回的每个文档计算一个新的评分

也就是修改返回结果中_score字段的值

Elasticsearch为用户预定义了如下函数

  • weight:表示为每个文档应用一个简单的权重:当weight为2时,最终结果为2 *_score。
  • field_value_factor:表示使用这个值来修改_score。
  • random_score:表示为每个用户都使用一个不同的随机评分。
  • 衰减函数:包括linear、exp、gauss等函数。
  • script_score:表示如果需求超出以上几种函数的范围,用户可以使用自定义脚本控制评分的计算。

2.1 DSL方式

GET /hotel/_search
{
  "_source": ["title","city"],
  "query": {
    "function_score": {
      "query": {                 //查询符合条件的文档
        "term": {
          "city": {
            "value": "北京"
          }
        }
      },
      "functions": [             //定义函数
        {                        //此处只定义了一个函数:随机数函数
          "random_score": {}
        }
      ],
      "score_mode": "sum"        //最终分数是各个函数的加和值
    }
  }
}

2.2 Java 客户端方式

在Java客户端中使用Function Score进行查询时,

可以调用ScoreFunctionBuilders.randomFunction()方法新建一个随机函数,

然后将该随机函数的实例传给QueryBuilders.functionScoreQuery()方法生成FunctionScoreQueryBuilder的实例

public void functionScoreSearch() {
    //创建搜索请求
    SearchRequest searchRequest = new SearchRequest("hotel");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //构建term查询
    TermQueryBuilder termQuery = QueryBuilders.termQuery("city", "北京");
     //构建随机函数
    ScoreFunctionBuilder<?> scoreFunction = ScoreFunctionBuilders.randomFunction();
    //构建Function Score查询
    FunctionScoreQueryBuilder funcQuery = QueryBuilders.functionScoreQuery(
        termQuery, scoreFunction).boostMode(CombineFunction.SUM);
    searchSourceBuilder.query(funcQuery);
    searchRequest.source(searchSourceBuilder);  //设置查询请求
   printResult(searchRequest);                  //打印搜索结果
}

2.3 weight权重函数查询

GET /dbindex/_search
{
  "query": {
    "function_score": {
      "query": { "match_all": {} },
      "boost": "5",
      "functions": [
        {
          "filter": { "match": { "test": "bar" } },
          "weight": 1
        },
        {
          "filter": { "match": { "test": "cat" } },
          "weight": 2
        }
      ]
    }
  }
}

2.4 field_value_factor

可以调用field_value_factor函数通过文档中的某一个字段来计算评分

GET /dbindex/_search
{
  "query": {
    "function_score": {
      "field_value_factor": {
        "field": "my-int", // 表示要从文档中提取的字段
        "factor": 1.2,     // 表示字段值相乘的可选因子,默认值为1
        "modifier": "sqrt",// 表示使用的计算公式, 默认为none
        "missing": 1
      }
    }
  }
}

以上语句中的函数将转化为以下公式来计算评分, sqrt(1.2 * doc['my-int'].value)

modifier中可选的公式以及各个公式的含义:

  • none: 不做任何计算
  • log:取字段值的常用对数
  • log1p:在字段值上加1,然后取常用对数
  • log2p:在字段值上加2,然后取常用对数
  • ln:取字段值的自然对数
  • ln1p:在字段值上加1,然后取自然对数
  • ln2p:在字段值上加2,然后取自然对数
  • square: 取字段值的平方
  • sqrt: 取字段值的平方根
  • reciprocal: 取字段值的倒数

举个例子

GET /dbindex/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query":    "popularity",
          "fields": [ "title", "content" ]
        }
      },
      "field_value_factor": {
        "field":    "votes",
        "modifier": "log1p"
      }
    }
  }
}

最终的分数计算公式为:new_score = old_score * log(1 + number_of_votes)

2.5 random_score函数查询

GET /dbindex/_search
{
  "query": {
    "function_score": {
      "query": { "match_all": {} },
      "boost": "5",
      "functions": [
        {
          "filter": { "match": { "test": "bar" } },
          "random_score": {},
          "weight": 23
        },
        {
          "filter": { "match": { "test": "cat" } },
          "weight": 42
        }
      ],
      "max_boost": 42,
      "score_mode": "max", // 最终分数是各个函数最高分
      "boost_mode": "multiply",
      "min_score": 42
    }
  }
}

score_mode:

  • multiply: 评分的倍数
  • sum: 评分之和
  • avg: 评分的平均值
  • first: 第一个匹配改文档的评分
  • max: 评分中最高的的分数
  • min: 评分中最低的分数

2.6 script_score脚本分数

script_score函数允许用户嵌套一个查询条件,并使用脚本表达式计算评分

GET /dbindex/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": { "message": "Elasticsearch" }
      },
      "script_score": {
        "script": {
          "source": "Math.log(3 + doc['my-int'].value)"
        }
      }
    }
  }
}
  • 所有文档分数都是正的32位浮点数。
  • 如果script_score函数计算出来更精确的评分,它将被转换为最接近的32位浮点数。
  • 必须保证评分是非负的,否则Elasticsearch将会返回一个错误信息。

三、提高评分查询

提高评分(boosting)查询不同于布尔查询,在布尔查询中只要一个子查询的条件不匹配,那么此文档数据就不符合要求。

提高评分查询其实是降低文档评分

比如查询条件是"name = 'clay' and address ='china'",对于只满足部分条件的文档数据,不是不返回,而是降低显示的优先级(也就是评分字段的值)

查询content字段中是否包含apple,并对包含pie的文档数据做降级处理(降低评分)

GET /dbindex/_search
{
  "query": {
    "boosting": {
      "positive": {
        "term": {
          "content": "apple"
        }
      },
      "negative": {
        "term": {
          "content": "pie"
        }
      },
      "negative_boost": 0.5 // 此值小于1表示降低评分,大于1表示提高评分
    }
  }
}

四、最佳匹配查询

dis_max指的是在文档匹配评分中,只将最佳匹配的评分作为查询的评分结果返回。

GET /dbindex/_search
{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "brown fox" }},
                { "match": { "body":  "brown fox" }}
            ],
            "tie_breaker": 0
        }
    }
}
朗读
赞 · 0
版权属于:

IT技术分享

本文链接:

https://idunso.com/archives/2871/(转载时请注明本文出处及文章链接)