我有一个大型的电子商务网站数据集。对于商人,我想显示每件商品的销售汇总,粒度为1天,汇总的日期范围从1天到最长1年不等,按销售额排序。
对于每个项目,都有一个与之关联的filterId。因此,在计算聚合之前,以下过滤器会逐步应用于Elasticsearch查询中:
merchantId-> filterId->日期范围->按项目和总和分组->排序
一种可能的数据建模方法是使用嵌套文档:
{
merchantId: testMerchant,itemId: testItem,filterId: testFilter:
perDaySales: [
{
orderDate: 2019-08-01,sales: 100
},{
orderDate: 2018-10-01,sales: 100
}
]
}
但是,问题是我们对filterId的更新率很高(每秒500次更新)。因此,如果我们更新一项的filterId,elasticsearch必须重新索引365个文档(因为我们存储了最后365个日期的数据,并且嵌套字段存储为单独的文档)。这似乎是一个过大的杀伤力。由于此连续索引编制,搜索延迟显着增加。此外,由于索引大量文档而导致JVM压力迅速增加,GC频繁启动。
或者,如果使用父子关系,则聚合非常慢。由于这是面向用户的,所以我不希望响应速度很慢。
其他可能性是使用应用程序侧连接。将itemId到filterId映射存储在其他索引或其他数据存储中。获取给定filterId的所有itemId,然后将这些itemId作为过滤器传递给elasticsearch查询。但是,一个商人可以拥有成千上万的商品。因此在ES查询中传递如此大的列表是不可行的。我无法将部分商品列表传递给查询,因为我需要按商品的销售降序显示结果页面。因此,要对所有项目进行排序,ES查询需要预先列出所有项目的列表。
在这种情况下,是否存在一种有效的方法来对数据进行建模,以使索引率在不影响聚合性能的情况下不会成倍增加?