elasticsearch - Elasticsearch:无法使用 script_score 排序结果
问题描述
我的弹性搜索索引中有一个名为price的字段,我需要在排序之前转换其值 -
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "products",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"prod_id" : 1,
"currency" : "USD",
"price" : 1
}
},
{
"_index" : "products",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"prod_id" : 2,
"currency" : "INR",
"price" : 60
}
},
{
"_index" : "products",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"prod_id" : 3,
"currency" : "EUR",
"price" : 2
}
},
{
"_index" : "products",
"_type" : "_doc",
"_id" : "5",
"_score" : 1.0,
"_source" : {
"prod_id" : 5,
"currency" : "MYR",
"price" : 1
}
}
]
}
}
由于每个产品的价格currency field
不同,
我计划将每个产品的价格转换为美元,
使用script_score
这里推荐的功能 -
弹性搜索排序预处理
我尝试了以下查询 -
GET products/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [{
"script_score": {
"script": {
"params": {
"USD": 1,
"SGD": 0.72,
"MYR": 0.24,
"INR": 0.014,
"EUR": 1.12
},
"source": "doc['price'].value * params.doc['currency']"
}
}
}]
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
]
}
我收到一个错误 -
{
"error": {
"root_cause": [
{
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"doc['price'].value * params.doc['currency']",
" ^---- HERE"
],
"script": "doc['price'].value * params.doc['currency']",
"lang": "painless"
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "products",
"node": "5-fQ27BhSUKycVJ2SwyH4A",
"reason": {
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"doc['price'].value * params.doc['currency']",
" ^---- HERE"
],
"script": "doc['price'].value * params.doc['currency']",
"lang": "painless",
"caused_by": {
"type": "class_cast_exception",
"reason": "Cannot apply [*] operation to types [java.lang.Long] and [org.elasticsearch.index.fielddata.ScriptDocValues.Strings]."
}
}
}
]
},
"status": 400
}
预期产品序列 -
1. prod_id 3 , _score 2.24 = 2(price) * 1.12 (USD multiplier)
2. prod_id 1 , _score 1 = 1(price) * 1 (USD multiplier) = 1
3. prod_id 2 , _score 0.84 = 60(price) * 0.014 (USD multiplier)
4. prod_id 5 , _score 0.24 =1(price) * 0.24 (USD multiplier)
索引映射 -
{
"mapping": {
"properties": {
"currency": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"fielddata": true
},
"price": {
"type": "long"
},
"prod_id": {
"type": "long"
}
}
}
}
有人可以帮忙查询这个用例吗?
解决方案
由于currency
has type text
,它被标准分析器索引,将其转换为小写。
这意味着,当货币为 时MYR
,它的索引为myr
,因此脚本应类似于:
doc.currency.value == 'myr' ? params.MYR : 1
如果currency
是"type":"keyword"
,那么您可以使用:
doc.currency.value === 'MYR' ? params.MYR : 1
推荐阅读
- c# - 如何停止启用 Windows 10 功能“焦点辅助”?
- c# - 使用 Sevenzip 提取 .7Z 文件不适用于 >1GB 的较大文件
- python - DEAP:使个人的适应度取决于整个人口
- javascript - 在数据库(mysql)中存储位置坐标
- reactjs - Use Typescript in ReactJs
- java - How to make Thread/Job wait until the previous Job is finished and thereafter resume it on some Notification
- python - Splitting list of nested json to multiple columns
- django - 有没有办法在 django-mdeditor 中更改语言
- django - How can I render a template and link to a particular section of the page?
- c# - 下拉菜单未加载到所选项目