I have an elastic search index for firms, that has a nested object called transactions. The transactions have at least a date
I don't think you have other option than using a script
. Something like this:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "transactions",
"query": {
"bool": {
"must": [
{
"match": {
"transactions.side": "buyer"
}
},
{
"range": {
"transactions.date": {
"from": "2014-10-24",
"to": "2015-10-24"
}
}
}
]
}
}
}
},
{
"filtered": {
"filter": {
"script": {
"script": "if(_source.transactions.size<3) return false;fromDate=Date.parse('yyyy-MM-dd',fromDateParam);toDate=Date.parse('yyyy-MM-dd',toDateParam);count=0;for(d in _source.transactions){docsDate=Date.parse('yyyy-MM-dd',d.get('date'));if(docsDate>=fromDate && docsDate<=toDate){count++};if(count==3){return true;}};return false;",
"params": {
"fromDateParam":"2014-10-24",
"toDateParam":"2015-10-24"
}
}
}
}
}
]
}
}
}
The actual range
filter is an "optimization" for those documents where none of the dates matches. So that, this document (with no dates in the range) will not reach the more costly script
filter.
The script
itself first checks if the number of transactions is less than 3
. If it is, don't bother doing all the date checks and return false
. If it's more than 3
then take each date and compare with the parameters. As soon as a count of 3
is reached stop looking at the rest of the dates and return true
.