I decided to post here a solution because I spent too much time on it last week, hope it will help someone. I also need a review of you guyz, Elasticsearch experts, to be sure I understood concepts I'm talking about right here.
My situation was simple : I had to deal with nested objects in my ES Script Filter. Giving the application's architecture I'm working on, the only place I can manipulate them is inside of it. That means I was unable to use the official ES Nester Filter.
Here was my mapping (I changed attribute names to get the classical book example) :
mappings: {
book: {
properties: {
id: {
type: long
}
genre: {
type: string
}
title: {
type: string
}
reviews: {
properties: {
id: {
type: long
}
bookId: {
type: long
}
text: {
type: string
}
note: {
type: long
}
author: {
type: string
}
}
}
year: {
type: long
}
}
}
}
That means a book can have zero or many reviews. Once my Elasticsearch query ran, let's say I want to be able to use a script filter to filter the results and retain only recent books (2 years old max) with good reviews (>= 14 on a 20 scale) written par the New York Times. A recent book with a good note not given by New York Times (or the opposite) doesn't interest me.
Here is the content of my filter -> filter -> script -> script :
Calendar calendar = Calendar.getInstance();
yearWanted = calendar.get(Calendar.YEAR) - 2;
boolean yearTest = (doc['year'].?value >= yearWanted);
boolean reviewTest = false;
if (_source.reviews != null) {
for (review : _source.reviews) {
if (!reviewTest && review.author contains 'new york times' && review.note >= 14) {reviewTest = true;}
}
}
return (yearTest && reviewTest);
It works (juste remove the carriage returns) but I want to be sure of all the things above that I assume :
a script filter is played for every document in your index
-- if it returns true, the document iterated will be in the list returned
-- if it returns false, the document iterated will NOT be in the list returned
that means that if you want to list all documents in your index, a script="return false;" will work
always use lower case Strings in your script : ES stocks all String like this
Am I right ?
Last thoughts :
I wanted to use a break inside my for but it seems not possible with MVEL (how to break or continue in MVEL for / foreach loop)
a big thanks to Felix Hürlimann, his article (http://blog.squirro.com/post/45191175546/elasticsearch-and-joining) helped me a lot to understand the situation
Thank you guyz for your feedback :)
Have a great day !