Yes it's doable, your script is not doing that, though. Try using Groovy's any() method instead:
doc['array.key'].values.any{ it -> it >= min + doc['number'] && it <= max + doc['number'] }
A few things:
- Your script just goes over a collection and checks a condition, doesn't return a boolean value, and that's what you want
- you might consider changing the mapping for
number into an integer type
- not really sure why you have a field
array and inside it a nested field key. Couldn't you just have a field array that would be... and array? ;-)
- remember that in ES by default each field can be a single value or an array.
- As @Val has mentioned you need to enable dynamic scripting in your
conf/elasticsearch.yml but I'm guessing you've done it, otherwise you'd be getting exceptions.
A very simple mapping like this should work:
{
"mappings": {
"document": {
"properties": {
"value": {
"type": "integer"
},
"key": {
"type": "integer"
}
}
}
}
}
Example:
POST /documents/document/1
{
"number": 5,
"key": [
10,
5,
9,
20
]
}
POST /documents/document/2
{
"number": 5,
"key": [
70,
72
]
}
Query:
GET /documents/document/_search
{
"query": {
"bool": {
"filter": {
"script": {
"lang": "groovy",
"params": {
"max": 64,
"min": 6
},
"script": "doc['key'].values.any{ it -> it >= min + doc['number'] && it <= max + doc['number'] }"
}
}
}
}
}
Result:
{
"took": 22,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0,
"hits": [
{
"_index": "documents",
"_type": "document",
"_id": "1",
"_score": 0,
"_source": {
"number": 5,
"key": [
10,
5,
9,
20
]
}
}
]
}
}