elasticsearch - 弹性搜索 - 对嵌套文档进行排序和过滤
问题描述
我正在开发电子商务应用程序。目录数据由 Elastic Search 提供。我有已在 Elastic Search 中编入索引的 Product 文档。
文档看起来像这样(为了更好的可读性,排除了几个字段):
{
"title" : "Product Name",
"volume" : "200gm",
"brand" : {
"brand_code" : XXXX,
"brand_name" : "Brand Name"
},
"@timestamp" : "2021-08-26T08:08:11.319Z",
"store" : [
{
"physical_unit" : 0,
"default_price" : 115.0,
"_id" : "1234_111",
"product_code" : "1234",
"warehouse_code" : 111,
"available_unit" : 100
}
],
"category" : {
"category_code" : 987,
"category_name" : "CategoryName",
"category_url_link" : "CategoryName",
"super_category_name" : "SuperCategoryName",
"parent_category_name" : "ParentCategoryName"
}
}
上述文档中的 store 对象是 ES Query 将查找价格并确定商品是有货还是缺货的对象。
我想添加更多子对象来存储(基本上来自多个库存的数据)。每个产品最多可以有 150 多个子对象。
最终,产品文档将看起来像这样,其中多个库存数据映射到特定文档。
{
"title" : "Product Name",
"volume" : "200gm",
"brand" : {
"brand_code" : XXXX,
"brand_name" : "Brand Name"
},
"@timestamp" : "2021-08-26T08:08:11.319Z",
"store" : [
{
"physical_unit" : 0,
"default_price" : 115.0,
"_id" : "1234_111",
"product_code" : "1234",
"warehouse_code" : 111,
"available_unit" : 100
},
{
"physical_unit" : 0,
"default_price" : 125.0,
"_id" : "1234_112",
"product_code" : "1234",
"warehouse_code" : 112,
"available_unit" : 100
},
{
"physical_unit" : 0,
"default_price" : 105.0,
"_id" : "1234_113",
"product_code" : "1234",
"warehouse_code" : 113,
"available_unit" : 100
}
Upto N no of stores
],
"category" : {
"category_code" : 987,
"category_name" : "CategoryName",
"category_url_link" : "CategoryName",
"super_category_name" : "SuperCategoryName",
"parent_category_name" : "ParentCategoryName"
}
}
功能要求:
- 对于任何产品,我们都应该显示所有仓库的最低价格。对于 EX:如果特定产品有 50 个商店映射到它,则 Elastic Search 查询应该查看嵌套对象并获取所有 50 个商店中最低的值(如果项目可用)。
- 性能不应降低。
挑战:
- 如果我们开始为每种产品存储这么多商店,数据将会非常高。这会是个问题吗?
- 从嵌套文档中提取最低价格的有效方法是什么?
- 方面如何在嵌套文档中工作?就像我应用价格范围过滤器 ES 拾取之前未显示的数据一样。(它可能会从与范围匹配的其他商店中挑选数据)
我们使用模板查询ES,Elastic Search的版本是6.0。提前致谢!!
解决方案
首先,7.x 版对嵌套文档搜索进行了改进,值得升级。
至于6.x版本,有很多因素我无法给你一个具体的答案。看起来您可能不了解嵌套文档的工作方式,它们不是关系型的。
特别是当您说每个产品可能有 50 个映射到它的商店时,这听起来像是在暗示一种关系,而嵌套文档不存在这种关系。但是,来自这 50 个存储的值将存储在嵌套在父文档下的索引中。在一个产品或类别下拥有 50 家商店听起来并不重要。
自从引入聚合框架以来,ElasticSearch 并没有真正谈论过方面。并不是说它们不存在,只是不讨论它们的方式。
所以让我们试试这个。ElasticSearch 通过分而治之的机制优化其搜索和查询。数据分布在几个分片中,一个可配置的数字,每个分片负责审查自己的数据。此外,这些分片可以分布在多台机器上,以便有许多 cpu 和大量内存用于搜索。因此,如果您愿意扩大集群,那么增加数据并不重要,因为可以维持每台机器执行与以前相同的工作量的情况。
与关系数据库不同,过滤器搜索词允许 Elastic 大幅减少它正在查看的数据,并且更多的过滤器将提高关系数据库性能下降的性能。
现在回到嵌套文档。它们存储为单独的索引,但不是将结果映射到嵌套文档,而是将结果映射到父文档 ID。因此,您嵌套的文档与文档的其余部分并不完全相同,尽管它们也不是真正分开的。但这确实意味着嵌套文档对父文档的查询性能的影响应该很小。但是,如果您的数据大小超出当前系统的容量,您仍然需要增加其大小。
至于如何查询,您将使用弹性聚合。这些将允许您计算您的“方面”计数并确定最佳价格。Elastic 聚合非常强大且速度非常快。有一些有据可查的警告,但总的来说,它们会按您的预期工作。
在版本 6.x 中,查询字符串查询无法访问嵌套文档中的搜索条件,必须使用复杂查询。
回顾一下
功能要求:
- 对于任何产品,我们都应该显示所有仓库的最低价格。对于 EX:如果特定产品有 50 个商店映射到它,ElasticSearch 查询应该查看嵌套对象并获取所有 50 个商店中最低的值(如果项目可用)。
是的,嵌套聚合可以做到这一点。
- 性能不应降低。
性能将继续取决于数据大小与整体集群大小的比率。
挑战:
如果我们开始为每种产品存储这么多商店,数据将会非常高。这会是个问题吗?
不,这应该不是问题
从嵌套文档中提取最低价格的有效方法是什么?
弹性聚合
方面如何在嵌套文档中工作?就像我应用价格范围过滤器 ES 拾取之前未显示的数据一样。(它可能会从与范围匹配的其他商店中挑选数据)
是的,过滤可以很好地与聚合一起使用。聚合将基于过滤的数据。实际上,您可以仅基于最低价格进行聚合,然后在同一查询中使用您的价格范围进行聚合,这将为您提供在该价格范围内具有商店的文档的数量,并且您可以有一个子聚合显示每个价格范围下的商店。
我们使用模板查询ES,Elastic Search的版本是6.0。提前致谢!!
我对模板一无所知。ElasticSearch API 非常简单,我不知道为什么有人在 API 之上使用其他工具,它们只是增加了权重,增加了复杂性,并使关键功能不可用,因为包装器作者没有通过该功能。
推荐阅读
- heroku - ROOT_URL 未定义 | 推送导致构建失败
- c++ - 枚举所有分区并测试它们是否为 NTFS
- c++ - 编写一个自定义的、高度专业化的、专用的、符合标准的 C++ 分配器
- javascript - 当数据大于 0(零)时,Ajax Jquery / JavaScript 创建 HTML 元素
- javascript - 在javascript中转换负华氏数
- git - 问题的正确 GitHub 工作流程
- python - 如何从嵌套字典中的相同键名中获取多个不同的值?
- python-3.x - 如何让kivy只点击顶部的小部件
- javascript - 检查脚本是否已加载(并且对象存在于窗口空间中)的最佳实践?
- html - Textarea占位符字体大小html css