Похоже, что вы хотите добиться поведения, аналогичного UNION в SQL, поскольку сначала вы хотите разделить результирующий набор на 2 группы, отсортировать каждую группу, а затем присоединить одну группу за другой.
Есть несколько способов сделать это.
1) Выполнив 2 запроса
Как и в этот ответ , предлагается сделать 2 запроса:
POST /orders/_search
{
"query": {
"range": {
"count": {
"gt": 0
}
}
},
"sort" : [
{"site_price": "asc"},
]
}
POST /orders/_search
{
"query": {
"range": {
"count": {
"gte": 0,
"lte": 0
}
}
},
"sort" : [
{"site_price": "asc"},
]
}
И затем присоединение к ним на стороне клиента.Есть также способ сделать это полностью на стороне Elasticsearch.
2) Используя сортировку скриптов
Мы можем использовать сортировку на основе скриптов и сортировать сначала по доступности(count > 0
), затем по цене:
POST /orders/_search
{
"sort" : [
{
"_script" : {
"type" : "number",
"script" : {
"lang": "painless",
"source": "if (doc['count'].value > 0) { 1 } else { 0 } "
},
"order" : "desc"
}
},
{"site_price": "asc"}
]
}
Однако выполнение сценариев всегда приводит к снижению производительности.Решение № 1 является более надежным, хотя и выполняет 2 запроса.
Вот еще одно решение, которое использует один запрос и не использует дорогостоящие сценарии.
3) Добавление нового поля - для сортировки
Если мы добавим специальное поле "available"
, нам не нужно будет использовать сортировку скриптов.
Документы могут выглядеть следующим образом:
doc1 = {
"id": 1,
"site_price": 10,
"count": 0,
"available": 0
}
doc2 = {
"id": 2,
"site_price": 5,
"count": 5,
"available": 1
}
Тогда сортировка будетвыглядят так:
POST /orders/_search
{
"sort" : [
{"available": "desc"},
{"site_price": "asc"}
]
}
Это общий шаблон, называемый денормализация , который оказывается полезным при настройке на лучшую производительность.
Надеюсь, это поможет!