我在如何最好地在Elasticsearch中存储数据方面遇到问题。我希望它能够以将返回给用户的确切格式存储数据。我也不想在从Elasticsearch获得结果之后进行任何处理。我将汇总查询以基于可能的过滤器获取数据计数。
我有一个API端点,该端点使用户可以按名称搜索公司并以以下格式返回结果:
{
"company": {
"name": "KFC",
"status": "running",
"Cuisine": "Kentucky Fried Chicken"
},
"mainRestaurant": {
"location": {
"road": "main road",
"city": "New York City",
"state": "New York",
"country": "USA"
},
"status": "running",
"type": "Flagship restaurant"
}
}
此数据从公司数据库和餐馆数据库一起推送。根据以下条件从餐馆列表中选择mainRestaurant
:
*如果有旗舰餐厅,请使用它。
*如果没有,则使用数据库中找到的第一个餐厅,其中有一个名为important
的特定标志设置为true。
*如果没有,请选择您在数据库中找到的第一个。
所有公司都将拥有一个旗舰餐厅,因此,当没有应用位置过滤器时,上述逻辑就不会成为问题,因为mainRestaurant
将始终是公司的旗舰餐厅。但是,如果传入一个位置,则很可能我们将继续进行逻辑的后续部分。
我想要做的是从Elasticsearch为每个公司的每个公司获取单个结果,而我的计划是为每个公司的每个地点添加一个结果。因此,该索引只会在每个位置保存肯德基(以及其他公司)的主要餐厅。因此,对于纽约,它将存储以上结果,对于伦敦,它将存储如下结果:
{
"company": {
"name": "KFC",
"status": "running",
"Cuisine": "Kentucky Fried Chicken"
},
"mainRestaurant": {
"location": {
"road": "main road",
"city": "London",
"state": "England",
"country": "UK"
},
"status": "running",
"type": "important restaurant"
}
}
这里的问题是,Elasticsearch中现在每个公司都有多个结果,而没有一种简单的方法可以在单个查询中获取最佳结果。为此,我的解决方案是使用一些元数据在对象周围添加包装器。因此,对于第一个结果(肯德基旗舰店):
{
"bestRestaurantIn": ["*", "USA", "New York", "New York City"],
"result": {
... data ...
}
}
对于伦敦重要的餐厅,它看起来像这样:
{
"bestRestaurantIn": ["UK", "England", "London"],
"result": {
... data ...
}
}
对于曼彻斯特最好的餐厅,它是这样的:
{
"bestRestaurantIn": ["Manchester"],
"result": {
... data ...
}
}
因此,如果您不传递位置,则可以在存在*
的地方添加一个term子句,以便对于“肯德基”公司,在bestRestaurantIn中只有带有*
的那个搜索时将返回该字段。如果您将“曼彻斯特”作为位置过滤器传递,它将仅获得曼彻斯特的肯德基,因为在曼彻斯特,肯德基只有一个结果。
以下是在名称中搜索“ kf”时的一些示例。它应该给出:
因此,如果还有一家名为“ KFB”的餐厅(假设Elasticsearch中没有其他名称与搜索“ KF”匹配的结果),那么每个位置最多只能返回2个结果,在某些情况下如果公司在特定位置没有餐厅,则为1或0。
上述解决方案可以正常工作。然而,当添加更多过滤器时,这成为一个问题。餐厅数据库中的每个餐厅都有一个状态。可以是“正在运行”或“关闭”。这意味着我们将需要为每个位置的每个公司添加一个“正在运行的”餐厅和一个“关闭”餐厅(如果有)。我们还需要在包装器中添加一个标志,例如“ isBestWithNoFilters”,它可能是“正在运行的”餐厅。
我的问题是,这根本无法很好地扩展。如果我需要在餐厅级别添加多个,那么这将变得异常复杂。有没有我应该遵循的模式?
很抱歉,很长的帖子。我希望我已经说清楚了!