I have an index with a mapping with a field like this:
"some_date_field": {
"type": "date"
}
and when that field has a value of null
, through a painless script it comes as a DateTime
representing the epoch (and some other strange behaviour I didn't know before), which just confused me for a couple of hours.
The following query:
{
"size": 1,
"query": {
"constant_score": {
"filter": {
"bool": {
"must_not": [
{
"exists": {
"field": "some_date_field"
}
}
]
}
}
}
},
"_source": [
"some_date_field"
],
"script_fields": {
"s": {
"script": "params._source['some_date_field']"
},
"d.f.values": {
"script": "doc['some_date_field'].values"
},
"d.f.values.string": {
"script": "doc['some_date_field'].values.toString()"
},
"d.f.value": {
"script": "doc['some_date_field'].value"
},
"d.f.value.string": {
"script": "doc['some_date_field'].value.toString()"
}
}
}
gives me the following response:
{
"took": 6,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 6763,
"max_score": 1,
"hits": [
{
"_index": "XXX",
"_type": "XXX",
"_id": "XXX",
"_score": 1,
"_source": {
"some_date_field": null
},
"fields": {
"s": [
null
],
"d.f.values.string": [
"[]"
],
"d.f.value": [
"1970-01-01T00:00:00.000Z"
],
"d.f.value.string": [
"1970-01-01T00:00:00.000Z"
]
}
}
]
}
}
Notice that:
- [expected] the source has
null
, everywhere - [unexpected]
d.f.values
is not on the response (empty lists are not a valid value?) - [unexpected]
d.f.values.string
shows thatd.f.values
is an empty list - [unexpected]
d.f.value
comes as the string of the epoch DateTime - [unexpected]
d.f.value.string
comes as the string of the epoch DateTime, showing that it was not a post-processing transformingnull
into that value (it is that value inside the script context)
This is part of a migration from 2.4.6 to 6.3.0, which made me realize that a null
date field doesn't have the same behaviour it used to have on groovy scripts when on boolean contexts.
I see/know though (I've just tested on my old cluster) that in groovy/es@2.4, date fields used to be represented as 0
whenever d.f.value
was obtained, which is the millis equivalent to the epoch, making the new behaviour kinda expected with regards to compatibility. However, neither ES versions have anything on the docs mentioning that a null
value on date fields will be handled differently (the null_value
section on the date datatype says it will be handled as null
|| missing), so I'm willing to say that this has always been confusing or wrong.
If this is by design, I'd love to be lectured on why, and the docs could gain some extra words to help clarify this.