I'm trying to create a sorting script with painless, filtering nested documents. The reason I'm doing this with a script, is because I need to emulate a COALESCE statement.
My documents have titles stored like:
{
title: [
{
type: MainTitle,
value: [
{
language: eng,
label: The title
},
{
language: ger,
label: Das title
}
]
},
{
type: AvailabilityTitle,
value: [
{
language: eng,
label: New thing!
}
]
}
]
}
title and title.value are nested documents.
I want to sort documents primarily by their english MainTitle and by their german MainTitle only if no english MainTitle exists - even if the german title gave a higher score.
I'm trying to simply sort by the english MainTitle first to try it out and this is the script:
def source = params._source;
def titles = source.title;
if (titles != null && titles.length > 0) {
for(int i=0; i < titles.length; i++) {
def t = titles[i];
if (t.type == 'MainTitle') {
def values = t.value;
if (values != null && values.length > 0) {
for (int j = 0; j < values.length; j++) {
def v = values[j];
if (v.language == 'eng') {
return v.label;
}
}
}
}
}
}
return \"\";
For some reason I'm getting a null_pointer_exception
"script_stack": [
"if (values != null && values.length > 0) { ",
" ^---- HERE"
],
I don't get how values can be null at that point since I'm specifically checking for null just before it.
The null_pointer_exception is thrown, not because values
is null, but because values
does not have a method/function called length
. That is because for some reason values
is an ArrayList even though titles
earlier is an Array. Apparently they both have the method/function size()
so I can just use that.
So this works:
def source = params._source;
def titles = source.title;
if (titles != null && titles.size() > 0) {
for(int i=0; i < titles.size(); i++) {
def t = titles[i];
if (t.type == 'MainTitle') {
def values = t.value;
if (values != null && values.size() > 0) {
for (int j = 0; j < values.size(); j++) {
def v = values[j];
if (v != null && v.language == 'fin') {
return v.label;
}
}
}
}
}
}
return '';