Отслеживание доступности с помощью Algolia

Я работаю над веб-сайтом, похожим на Airbnb, и сейчас переписываю нашу внутреннюю поисковую систему на основе SQL с помощью Algolia. До сих пор это было действительно приятное путешествие, так как мне удалось удалить много устаревшего кода и передать его на аутсорсинг с потрясающими результатами. Однако есть одна важная часть нашей поисковой системы, которую я не уверен, можно ли реализовать с помощью Algolia.

Внутри мы сохраняем доступность/недоступность (и цену) каждой даты для каждого актива в виде одной строки в базе данных. Это означает, что наша таблица availabilities выглядит так:

asset_id | date       | status      | price_cents
-------- | ---------- | ----------- | -----------
1        | 2017-02-09 | available   | 15000
1        | 2017-02-10 | available   | 15000
1        | 2017-02-11 | unavailable | NULL
1        | 2017-02-12 | available   | 20000

Когда пользователь ищет доступные свойства, он вводит диапазон дат и, при необходимости, диапазон цен.

Что мы делаем сейчас, так это просто запрашиваем таблицу availabilities и убеждаемся, что все даты в диапазоне дат доступны для этого актива (т. е. количество доступных дат равно количеству дней в диапазоне). Если пользователь вводит диапазон цен, мы также следим за тем, чтобы средняя цена на эти даты находилась в пределах запрошенного диапазона. SQL-запрос довольно сложен, но именно это он и делает в конце дня.

Я пытался воспроизвести это с помощью Algolia, но не смог найти никакой документации о подобной функции. На самом деле, я сталкиваюсь с двумя отдельными проблемами прямо сейчас:

  • У меня нет возможности гарантировать, что все даты в предоставленном диапазоне дат доступны, потому что Algolia практически не знает об ассоциациях, и
  • У меня нет возможности рассчитать (и запросить) среднюю цену для указанного диапазона дат, потому что она зависит от ввода пользователя (т.е. диапазона дат).

Есть ли способ добиться этого с Алголией? Если нет, возможно ли использовать SQL или другой инструмент в сочетании с Algolia для достижения желаемого результата? Конечно, я мог бы сделать все это с помощью Elasticsearch, но Algolia настолько быстр и удобен, что мне не хотелось бы отказываться от него из-за этих проблем.


person Alessandro Desantis    schedule 09.02.2017    source источник


Ответы (1)


Этот вариант использования определенно сложен, и для работы Algolia нужны предварительно вычисленные данные.


Редактировать 2020 (лучшее решение)

В каждом элементе вы можете просто сохранить список дней, когда местоположение доступно, например.

{
  name: "2 bedroom appartment",
  location: "Paris",
  availabilities: ['2020-04-27', '2020-04-28', '2020-04-30']
  price_cents: 30000
}

Затем вы можете во время поиска создать список всех доступных вам предметов, например. (доступно с 28 по 30 апреля):

index.search('', {
  filters: '' +
    'availabilities:2020-04-28 AND availabilities:2020-04-29 AND availabilities:2020-04-30 AND ' +
    'price_cents >= ' + lowPriceRange + ' AND price_cents <= ' + highPriceRange 
}) 

В этом примере запись не будет соответствовать, поскольку в ней отсутствует 2020-04-29.


Другое решение, которое работает более универсально, но требует гораздо больше записей:

Я предполагаю, что существует ограничение на количество дней, за которые вы можете бронировать заранее, здесь я предполагаю, что это 90 дней.
Вы можете сгенерировать все возможные диапазоны дат в течение этих 90 дней.
Это означало бы создание 90 + 89 + ... = 90 * 91 / 2 = 4095 диапазонов дат.
Затем для каждого из этих диапазонов и каждой квартиры, которую вы предлагаете в своем сервисе, вы можете создать такой объект:

{
  name: "2 bedroom appartment",
  location: "Paris",
  availability_range: "2017-02-09 -> 2017-02-10",
  availability_start_timestamp: 10001000,
  availability_end_timestamp: 10002000,
  price_cents: 30000
}

С этими объектами поиск диапазона дат будет таким же простым, как:

index.search('', {
  filters: '' +
    'availability_range:"' + startDate + ' -> ' + endDate + '" AND ' +
    'price_cents >= ' + lowPriceRange + ' AND price_cents <= ' + highPriceRange 
}) 

Вы будете индексировать только доступные временные диапазоны, поэтому это должно значительно уменьшить количество объектов, но, вероятно, оно все равно будет огромным.

Наконец, временные метки в объекте будут здесь, чтобы знать, какие из них следует удалить при бронировании. Вызов будет примерно таким:

index.deleteByQuery('', {
  filters: 'availability_start_timestamp < ' + booking_end_timestamp + ' AND availability_end_timestamp > ' + booking_start_timestamp
})
person Jerska    schedule 09.02.2017
comment
К сожалению, мы сохраняем наличие мест на весь год. Есть ли способ использовать SQL для фильтрации до или после Алголии? - person Alessandro Desantis; 09.02.2017
comment
Тогда вы будете смотреть на 66795 диапазонов дат на квартиру, что, вероятно, действительно будет слишком дорого. - person Jerska; 10.02.2017
comment
Всегда ли ожидается, что список результатов будет низким (‹1000)? Например, вы также ограничиваете местоположение? Если да, вы могли бы использовать Algolia для получения списка идентификаторов объектов, соответствующих запросу текст + местоположение, и отправить этот список идентификаторов в MySQL для вычисления доступных из этого списка. - person Jerska; 10.02.2017
comment
Вы потеряете скорость Алголии, но все равно выиграете от ее текстовой релевантности. - person Jerska; 10.02.2017
comment
На данный момент у нас не будет много результатов, но в будущем мы можем. Насколько хорошо будет масштабироваться такое решение? Какие методы я могу использовать, чтобы сделать его более масштабируемым? - person Alessandro Desantis; 10.02.2017
comment
Что ж, как только ваш список результатов Algolia превысит 1000 пунктов, вы, вероятно, застрянете. Вы можете увеличить этот предел на порядок, но это не будет бесконечно масштабируемым. Но я предполагаю, что к тому времени у вас будут ресурсы, которые будут посвящены работе над этим. :) - person Jerska; 22.02.2017