_score doesn't update in a function score query with script

I'm trying to get some basic working by setting the _score of a document, using function scores and/or painless scripts. I plan to use the basic block to find the mechanism to build out my final use case. Sadly it already fails. My data looks like this:

{
    "brand": "Apple",
    "flavourScore": 1.1,
    "price": 6.5
}

I have 9 items (3 Apples, 3 Bananas, 3 Tomatoes, differing in flavourScore and price). I've created 1 mapping for the index where they are in (couldn't post messages otherwise).

All documents have a _score of 1 by default. Mildly strange, but as I want to recompute the _score I don't care that much. I had tried a few examples found here and there, adapted them, but there is little in the form of debugging you can do. So I decided ny first test would be to just reset all the _score values to a different constant (as they are all 1 now as well). However.....nothing gets updated on ES64 (Docker image). Any clues why the GET on the _search endpoint for this index fails:

{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "script_score": {
            "script": {
              "lang": "painless",
              "inline": "_score = 0.18;"
            }
          }
        }
      ],
      "boost_mode": "replace"
    }
  },
  "sort": [
    "_score"
  ]
}

I'd expect all _score values to be 0.18 when I do a match_all query, but they stay 1.

Any insights, examples, clues are highly appreciated - especially as my next step will to have the script compute the value for _score

Thanks,

Maarten

Let me try to simplify: I want to be able to change the score of my document based on field values (boost_mode: replace).

As first use case I tried to set all my 9 test documents to the same score (to prevent script errors from getting a result). But can't even get that to work.

Stange, copying and pasting a doc example (the third example) to sort doesn't work - and I just use the value of one field; doc['brand'].value

It's almost as if my index is "frozen" and does not allow any changes.

OK, so POSTing and returning a constant from the script sets the _score.

Now I added params['_source']['flavourScore']* and get:

"caused_by": {

* "type": "script_exception",
* "reason": "compile error",
* "script_stack": [
  * "params['_source']['price' ..."
,  * "^---- HERE"],
* "script": "params['_source']['price']; return 0.2",
* "lang": "painless",
* "caused_by": {
  * "type": "illegal_argument_exception",
  * "reason": "Not a statement."}

So once I figure out how to access the price parameter in the document I might be able to close in.

"inline": "_score = 0.18;"

This isn't a valid score script. It is unfortunate it compiles. Score scripts return the score. Here you are overriding the _score variable, but nothing reads this outside of the script. If you want the score to be 0.18, then your script should be return 0.18.

Yes, I got that working. However, I can't find a way to take the next step, using document variables to compute a new score. If I use either_source.varname or doc['varname'].value the script won't load and gives a null pointer exception at that location :frowning:

--Maarten

Can you show the exact request you are using?

Sure. I use POST, otherwise nothing happens. The only thing I did was testing a minimal step forward, just reading a doc parameter in two ways. I've also added the mapping (first):

{
  "mappings": {
    "_doc": {
      "properties": {
        "brand": {
          "type": "text"
        },
        "flavourType": {
          "type": "double"
        },
        "price": {
          "type": "double"
        }
      }
    }
  }
}

query 1:

{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "script_score": {
            "script": {
              "lang": "painless",
              "inline": "_source.price; return 0.2"
            }
          }
        }
      ],
      "boost_mode": "replace"
    }
  },
  "sort": [
    "_score"
  ]
}

query 2:
    {
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "script_score": {
            "script": {
              "lang": "painless",
              "inline": "params['_source']['flavourScore']; return 0.2"
            }
          }
        }
      ],
      "boost_mode": "replace"
    }
  },
  "sort": [
    "_score"
  ]
}

query 1 gives back:
"caused_by": {

* "type": "script_exception",
* "reason": "compile error",
* "script_stack": [
  * "_source.price; return 0.2"
,  * "^---- HERE"],
* "script": "_source.price; return 0.2",
* "lang": "painless",
* "caused_by": {
  * "type": "illegal_argument_exception",
  * "reason": "Variable [_source] is not defined."

and query 2 gives back:
"caused_by": {

* "type": "script_exception",
* "reason": "compile error",
* "script_stack": [
  * "params['_source']['price' ..."
,  * "^---- HERE"],
* "script": "params['_source']['price']; return 0.2",
* "lang": "painless",
* "caused_by": {
  * "type": "illegal_argument_exception",
  * "reason": "Not a statement."

...which both look similar. Am I doing something wrong in the mapping definition, or is there a flag I need to set. I'm using the latest Docker image.

I hope you can see what I'm doing wrong, haven't set up, .....

Thanks for your help so far and even looking at this!

Best, Maarten

I've figured it out. Here's the function score with script that did the trick for me (maybe in the future, someone else finds it useful - also a nice non-trivial use case for the docs?).

{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "script_score": {
            "script": {
              "lang": "painless",
              "inline": "if ((doc['price'].value > 8) && (doc['price'].value < 10)) {return doc['flavourScore'].value * 10} else {return doc['flavourScore'].value} "
            }
          }
        }
      ],
      "boost_mode": "replace"
    }
  },
  "sort": [
    "_score"
  ]
}

Both errors are because you have an expression but not a statement. A statement needs to be an assignment, return, or some other element of the language. Eg you can't just put foo on a line by itself (the semicolon make it its own line). You need to too foo = bar or bar = foo, or return foo, or something like that. Also note that in the first query, _source is not a valid variable; you need to access it through params as you are attempting to do in query 2.

I've figured it out.

Great!

also a nice non-trivial use case for the docs?

If you have a place in the docs in mind, we happily accept PRs. :slight_smile:

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.