简体   繁体   English

Elasticsearch:无法使用script_score排序结果

[英]Elasticsearch: Unable to order results using script_score

I have a field called price in my elasticsearch index whose values I need to convert before sorting - 我的Elasticsearch索引中有一个名为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
        }
      }
    ]
  }
}

As the currency field for each product is different, 由于每种产品的currency field不同,
I plan to convert each product's price into USD , 我计划将每种产品的价格转换为USD
Using the script_score function, as recommended here - 按照此处的建议使用script_score函数-
Elastic Search sort preprocessing 弹性搜索排序预处理

I tried the following query - 我尝试了以下查询-

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"
      }
    }
  ]
}

I'm getting an error - 我遇到错误-

{
  "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
}

Expected product sequence - 预期产品顺序-
1. prod_id 3 , _score 2.24 = 2(price) * 1.12 (USD multiplier) 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 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) 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) 4. prod_id 5 ,_score 0.24 = 1(price) * 0.24 (USD multiplier)

Index Mapping - 索引映射-

{
  "mapping": {
    "properties": {
      "currency": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        },
        "fielddata": true
      },
      "price": {
        "type": "long"
      },
      "prod_id": {
        "type": "long"
      }
    }
  }
}

Can someone please help for this use case query? 有人可以为这个用例查询提供帮助吗?

test 1 - 测试1- 在此处输入图片说明 test 2 - 测试2- 在此处输入图片说明 null_pointer_exception - 空指针异常 - 在此处输入图片说明

Since the currency has type text , it is indexed with Standard Analyzer which converts it to lower case. 由于currency类型为text ,因此使用Standard Analyzer对其进行了索引,从而将其转换为小写形式。

That means, when currency is MYR , it is indexed as myr , so the script should be something like: 这意味着,当currency为MYR ,其索引为myr ,因此脚本应类似于:

doc.currency.value == 'myr' ? params.MYR : 1

If currency is "type":"keyword" , then you can use: 如果currency"type":"keyword" ,则可以使用:

doc.currency.value === 'MYR' ? params.MYR : 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM