Я создаю небольшое приложение для поиска номеров в отелях, например, booking.com, используя Elasticsearch 6.8.0.
По сути, у меня есть документ на день и номер, в котором указано, доступен ли он, и стоимостьна этот день. Мне нужно выполнить запрос с этими требованиями:
Ввод:
- Дни желаемого пребывания.
- Максимальная сумма денег, которую я готов потратить.
- Страница результатов, которые я хочу видеть.
- Количество результатов на странице.
Вывод:
- Список самых дешевых предложений для каждой гостиницы, которые отвечают требованиям, заказанных в порядке ASC.
Схема документов:
{
"mappings": {
"_doc": {
"properties": {
"room_id": {
"type": "keyword"
},
"available": {
"type": "boolean"
},
"rate": {
"type": "float"
},
"hotel_id": {
"type": "keyword"
},
"day": {
"type": "date",
"format": "yyyyMMdd"
}
}
}
}
}
У меня есть индекс в месяц, и на данный момент я толькопоиск в том же месяце.
Я пришел с этим запросом:
GET /hotels_201910/_search?filter_path=aggregations.hotel.buckets.min_price.value,aggregations.hotel.buckets.key
{
"size": 0,
"query": {
"bool": {
"filter": [
{
"range": {
"day": { "gte" : "20191001", "lte" : "20191010" }
}
},
{
"term": {
"available": true
}
}
]
}
},
"aggs": {
"hotel": {
"terms": {
"field": "hotel_id",
"min_doc_count": 1,
"size" : 1000000
},
"aggs": {
"room": {
"terms": {
"field": "room_id",
"min_doc_count": 10,
"size" : 1000000
},
"aggs": {
"sum_price": {
"sum": {
"field": "rate"
}
},
"max_price": {
"bucket_selector": {
"buckets_path": {
"price": "sum_price"
},
"script": "params.price <= 600"
}
}
}
},
"min_price": {
"min_bucket": {
"buckets_path": "room>sum_price"
}
},
"sort_by_min_price" : {
"bucket_sort" :{
"sort": [{"min_price" : { "order" : "asc" }}],
"from" : 0,
"size" : 20
}
}
}
}
}
}
И это работает, но есть несколько проблем.
- Это слишком медленно,При 100 тыс. Ежедневных комнат на моем компьютере требуется около 500 мсек, когда не выполняется ни один другой запрос. Так что в реальной системе это было бы очень плохо.
- Мне нужно установить
"size"
на большое число в терминах агрегации, иначе не все отели и номера считаются.
Есть ли способ улучшить производительность этой агрегации? Я пытался разделить индекс на несколько сегментов, но это не помогло.
Я почти уверен, что подход неправильный, и поэтому он медленный. Любая рекомендация о том, как добиться более быстрого времени ответа на запрос в этом случае?