Elastic script_score, only count specific array elements

孤街醉人 提交于 2021-01-07 06:50:25

问题


I have a bunch of objects like this one in Elastic:

{
          "id" : "b397ab9c-2bab-4cce-a419-ba6b23545772",
          "name": "Alice",
          // other fields omitted
          "foo" : [
            {
              "id" : "1",
              "bar" : 20
            },
            {
              "id" : "2",
              "bar" : 20
            }
           ]
},
{
          "id" : "826784cb-7dcd-4d2c-b444-a466032a7b06",
          "name": "Bob",
          // other fields omitted
          "foo" : [
            {
              "id" : "1",
              "bar" : 15
            }
           ]
}

I am trying to make a score based on any elements in foo of which the id is 2. So in the above objects, Alice has a score of 20 and Bob has a score of 0 (as there's no element with id 2 in his foo array. I'm however a bit stuck in how to have my script_score look for the specific element. Here is my query:

  "query": {
    "function_score": {
      "score_mode": "max", 
      "functions": [
        {
          "filter": {
            "term": {
              "foo.id": {
                "value": "2"
              }
            }
          },
          "script_score": {
            "script": {
              "source": "doc['foo'].values /* what goes here? */",
              "params": {
              }
            }
          }
        }
      ]
    }
  }

回答1:


When foo is not of type nested, you'll have lost the connection between id and bar due to value flattenning.

After you've reconfigured your mapping to be nested, you can do

{
  "query": {
    "nested": {
      "path": "foo",
      "query": {
        "function_score": {
          "score_mode": "max",
          "functions": [
            {
              "script_score": {
                "script": {
                  "source": "if (doc['foo.id.keyword'].value == '2') { def bar = doc['foo.bar'].value; return bar } return 0",
                  "params": {}
                }
              }
            }
          ]
        }
      }
    }
  }
}

but without the filter because that'd have filtered out doc#2 since it does not meet that condition and you probably want to do some sort of a scripted fallback.

Do note that once you're in the nested context, you don't have access to other object groups in your foo array. In other words, when you're in id: 2, you don't see the id: 1 group. More info here.



来源:https://stackoverflow.com/questions/65073724/elastic-script-score-only-count-specific-array-elements

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!