Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using boolean fields in groovy script in elasticsearch - doc['field_name'].value not working

The problem

I am trying to use boolean fields in a script to score. It seems like doc['boolean_field'].value can't be manipulated as a boolean, but _source.boolean_field.value can (even though the Scripting documentation here says "The native value of the field. For example, if its a short type, it will be short.").

What I've tried

I have a field called 'is_new'. This is the mapping:

PUT /test_index/test/_mapping
{
  "test": {
    "properties": {
      "is_new": {
        "type": "boolean"
      }
    }
  }
}

I have some documents:

PUT test_index/test/1
{
    "is_new": true
}

PUT test_index/test/2
{
    "is_new": false
}

I want to do a function_score query that will have a score of 1 if new, and 0 if not:

GET test_index/test/_search
{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "script_score": {
            "script": "<<my script>>",
            "lang": "groovy"
          }
        }
      ],
      "boost_mode": "replace"
    }
  }
}

Scripts work when I use the _source.is_new.value field, but don't if I use doc['is_new'].value.

This works:

"if ( _source.is_new) {1} else {0}" 

These don't work:

"if ( doc['is_new'].value) {1} else {0}" (always true)

"if ( doc['is_new'].value instanceof Boolean) {1} else {0}" (value isn't a Boolean)

"if ( doc['is_new'].value.toBoolean()) {1} else {0}"  (always false)

"if ( doc['is_new']) {1} else {0}"  (always true)

I've checked the value, and it thinks it is a string, but I can't do string comparison:

"if ( doc['is_new'].value instanceof String) {1} else {0}"  (always true)

"if ( doc['is_new'].value == 'true') {1} else {0}"  (always false)

"if ( doc['is_new'].value.equals('true')) {1} else {0}" (always false)

Is this broken, or am I doing it wrong? Apparently it is faster to use doc['field_name'].value, so if possible, it would be nice if this worked.

I am using Elasticsearch v1.4.4.

Thanks! Isabel

like image 938
IBN Avatar asked Apr 22 '15 22:04

IBN


2 Answers

I'm having the same issue on ElasticSearch v1.5.1: Boolean values in the document show up as characters in my script, T' for true and 'F' for false:

if ( doc['is_new'].value == 'T') {1} else {0}

like image 199
chgeuer Avatar answered Oct 09 '22 21:10

chgeuer


I've just got it!

First, it works only with _source.myField, not with doc['myField'].value. I think there's a bug there because the toBoolean() method should return a boolean depending on the actual value, but it doesn't.

But I also needed to declare the mapping of the field explicitly as boolean and not_analyzed.

I hope it helps!

like image 28
David Vartanian Avatar answered Oct 09 '22 21:10

David Vartanian