1

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 :

Thank you guyz for your feedback :)

Have a great day !

4

0 回答 0