elasticsearch - ElasticSearch - 使用脚本提高分数
问题描述
我们的 ElasticSearch 实例有一个特定的用例:我们存储包含专有名称、出生日期、地址、身份证号和其他相关信息的文档。
我们使用了一个名称匹配插件,它会覆盖 ES 的默认评分,并根据名称匹配的程度分配 0 到 1 之间的相关性分数。
如果其他字段匹配,我们需要做的是将该分数提高一定数量。我已经开始阅读 ES 脚本来实现这一点。我需要有关查询脚本部分的帮助。现在,我们的查询如下所示:
{
"size":100,
"query":{
"bool":{
"should":[
{"match":{"Name":"John Smith"}}
]
}
},
"rescore":{
"window_size":100,
"query":{
"rescore_query":{
"function_score":{
"doc_score":{
"fields":{
"Name":{"query_value":"John Smith"},
"DOB":{
"function":{
"function_score":{
"script_score":{
"script":{
"lang":"painless",
"params":{
"query_value":"01-01-1999"
},
"inline":"if **<HERE'S WHERE I NEED ASSISTANCE>**"
}
}
}
}
}
}
}
}
},
"query_weight":0.0,
"rescore_query_weight":1.0
}
}
该Name
字段在查询中始终是必需的,是得分的基础,在默认_score
字段中返回;为了便于演示,我们将只添加一个额外的字段 ,DOB
如果匹配,应该会将分数提高 0.1。我相信我正在寻找类似的东西if(query_value == doc['DOB'].value add 0.1 to _score)
,或者类似的东西。
那么,为了实现这一点,在行中输入的正确语法是什么?inline
或者,如果查询需要其他语法修改,请告知。
编辑#1 - 重要的是要强调我们的DOB
领域是一个text
领域,而不是一个date
领域。
解决方案
拆分为单独的答案,因为这以不同的方式解决了问题(即 - 通过使用script_score
建议的 OP 而不是尝试重写脚本)。
假设与上一个答案相同的映射和数据,查询的脚本版本可能如下所示:
POST /employee/_search
{
"size": 100,
"query": {
"bool": {
"should": [
{
"match": {
"Name": "John"
}
},
{
"match": {
"Name": "Will"
}
}
]
}
},
"rescore": {
"window_size": 100,
"query": {
"rescore_query": {
"function_score": {
"query": {
"bool": {
"should": [
{
"match": {
"Name": "John"
}
},
{
"match": {
"Name": "Will"
}
}
]
}
},
"functions": [
{
"script_score": {
"script": {
"source": "double boost = 0.0; if (params['_source']['State'] == 'FL') { boost += 0.1; } if (params['_source']['DOB'] == '1965-05-24') { boost += 0.3; } return boost;",
"lang": "painless"
}
}
}
],
"score_mode": "sum",
"boost_mode": "sum"
}
},
"query_weight": 0,
"rescore_query_weight": 1
}
}
}
关于脚本的两个注意事项:
- 该脚本用于
params['_source'][field_name]
访问文档,这是访问文本字段的唯一方法。这要慢得多,因为它需要直接访问磁盘上的文档,尽管在重新评分的情况下这种惩罚可能不会太糟糕。如果字段是可聚合类型,您可以改为使用doc[field_name].value
,例如keyword
,date
或数字 DOB
这里直接与字符串进行比较。这是可能的,因为我们正在使用该_source
字段,并且文档的 JSON 将日期指定为字符串。这有点脆弱,但可能会成功
推荐阅读
- maven - 特定代理上的 java 测试失败
- java - TimeTCPClient 和 TimeUDPClient 都超时
- java - 使用 POJOS 多态反序列化 JSON
- oracle-apex - 具有自动完成功能的文本字段
- java - 当我按下按钮时,动作监听器不工作
- r - InvalidArgumentError: indices[127,7] = 43 is not in [0, 43) in Keras R
- python - 输入文件路径并传递给字符串文字
- pandas - Read XML file to Pandas DataFrame
- angular - @angular/platform-browser/platform-browser"' 没有导出成员 'HammerLoader'
- javascript - jQuery每个函数的结果怎么办?