Есть индекс с документами в виде товаров. У каждого товара есть поля price и locations. У locations тип nested, внутри находится массив объектов локаций. У каждой локации есть id и price. В индексе около 300000 документов, у каждого документа от 0 до 100 локаций. В запросе может как передаваться параметр locations, так и не передаваться. В параметре приходит список id локаций.
Задача стоит следующая:
- Если в запросе нет фильтров по локации, выдать список документов отсортированный по корневой цене
- Если в запросе есть фильтр по локациям, выдать список документов, отсортированный по наименьшей цене в любой из локаций переданных в запросе.
Для решения задачи был написан следующий painless скрипт:
def minPrice = Double.MAX_VALUE;
def maxPrice = 0;
def locationIds = new HashSet(params["locations"]);
for (def loc : params._source.locations) {
if (loc.price != null && loc.price instanceof String) {
loc.price = Double.parseDouble(loc.price);
}
if (locationIds.contains(loc.id) && loc.price != null) {
if (params["order"] == "desc" && loc.price > maxPrice) {
maxPrice = loc.price;
}
if (params["order"] == "asc" && loc.price < minPrice) {
minPrice = loc.price;
}
}
}
if (params["order"] == "asc" && minPrice != Double.MAX_VALUE) {
return minPrice;
}
if (params["order"] == "desc" && maxPrice != 0) {
return maxPrice;
}
return doc["price"].value;
В худших случаях, когда по остальным фильтрам проходит бОльшее число документов, количество операций на один запрос только в этом скрипте может доходить до 20 миллионов. Ответ эластика в данном случае занимает порядка двух секунд, что для производительности слишком много. Можно ли как-то оптимизировать скрипт? Или перестроить структуру таким образом, чтобы запрос проходил быстрее?