与Algolia的可用性跟踪

Ale*_*tis 12 search algolia

我正在一个类似Airbnb的网站上工作,我正在用Algolia重写我们内部的基于SQL的搜索系统.到目前为止,这是一段非常愉快的旅程,因为我已经设法删除了大量遗留代码并将其外包,结果非常棒.但是,我们的搜索系统中有一个关键部分我不确定可以用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
Run Code Online (Sandbox Code Playgroud)

当用户搜索可用属性时,他们会输入日期范围和(可选)价格范围.

我们现在正在做的只是查询availabilities表并确保日期范围内的所有日期都可用于该资产(即可用日期的计数等于该范围内的天数).如果用户输入价格范围,我们还会确保这些日期的平均价格在要求的范围内.SQL查询相当复杂,但这是它在一天结束时所做的事情.

我一直试图用Algolia复制这个,但找不到任何关于类似功能的文档.事实上,我现在面临两个不同的问题:

  • 我无法确保所提供的日期范围内的所有日期都可用,因为Algolia几乎没有关于协会的知识,并且
  • 我无法计算(和查询)所提供日期范围的平均价格,因为它取决于用户输入(即日期范围).

有没有办法与Algolia实现这一目标?如果没有,是否可以将SQL或其他工具与Algolia结合使用以达到预期效果?当然,我可以用Elasticsearch完成所有这些工作,但是Algolia如此快速和简单,我不愿意因为这些问题而离开它.

Jer*_*ska 2

这个用例肯定很复杂,Algolia 需要预先计算的数据才能工作。


编辑2020(更好的解决方案)

在每个项目中,您可以简单地存储该位置可用的天数列表,例如

{
  name: "2 bedroom appartment",
  location: "Paris",
  availabilities: ['2020-04-27', '2020-04-28', '2020-04-30']
  price_cents: 30000
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以在搜索时生成您要求商品具有的所有可用性的列表,例如(4 月 28 日至 4 月 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 
}) 
Run Code Online (Sandbox Code Playgroud)

在此示例中,记录将不匹配,因为它缺少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
}
Run Code Online (Sandbox Code Playgroud)

有了这些对象,搜索日期范围就很简单:

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

您只会索引可用的时间范围,因此这应该大大减少对象的数量,但它仍然可能很大。

最后,对象中的时间戳将用于了解预订时要删除哪些时间戳。该调用将类似于:

index.deleteByQuery('', {
  filters: 'availability_start_timestamp < ' + booking_end_timestamp + ' AND availability_end_timestamp > ' + booking_start_timestamp
})
Run Code Online (Sandbox Code Playgroud)