There is an index with documents in the form of products. Each product has the price and locations fields. The locations type is nested, and there is an array of location objects inside. Each location has an id and a price. There are about 300000 documents in the index, each document has from 0 to 100 locations. The request may or may not pass the locations parameter. The parameter contains a list of location IDs.
The task is as follows:
- If there are no location filters in the request, it should return a list of documents sorted by root price
- If the request has a filter by location, it should return a list of documents sorted by the lowest price in any of the locations transmitted in the request.
The following painless script was written to solve the problem:
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;
In the worst cases, when a larger number of documents pass through the other filters, the number of operations per request in this script alone can reach up to 20 million. The elastic response in this case takes about two seconds, which is too much for performance. Is there any way to optimize the script? Or rebuild the structure in such a way that the request goes faster?