0

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": {
              }
            }
          }
        }
      ]
    }
  }
yesman
  • 7,165
  • 15
  • 52
  • 117

1 Answers1

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.

Joe - GMapsBook.com
  • 15,787
  • 4
  • 23
  • 68