【问题标题】:$lookup won't use indexes in second $match. How can we scale?$lookup 不会在第二个 $match 中使用索引。我们如何扩展?
【发布时间】:2020-01-19 14:51:58
【问题描述】:

在 MongoDB 3.6 中,我们有一个集合 Products,目前有 150k 个文档,我们需要为每个产品存储每个商店的价格。目前大约有1000家商店。

我们的策略是创建第二个集合,我们称之为ProductShops

{
    _id: "product_shop_id_1",
    productId: "product_id_1",
    shopId: "shop_id_1",
    price: 15,
    stock: 3,
    enabled: true
}

因为我们需要在两个集合中使用过滤器进行查询,例如获取X店有货,属于Y类的产品(产品类存储在Products集合中),我们将对产品集合进行聚合查询,过滤结果,然后查找到ProductShops收集,然后再次过滤结果。

聚合管道如下所示:

[
    match,
    sort,
    lookup,
    unwind,
    match,
    project,
    skip,
    limit
]

然而问题是,正如 mongodb 的文档中所述,第二个匹配项不会使用索引,这使得在处理数百万个文档时查找无用,并且请求恰好扫描整个集合(例如,当结果是小于限制)。我们对其进行了测试,在我们当前的数据大小下,它可能需要长达 30 秒。

我们尝试使用$lookup 的新语法,它允许嵌入管道并在那里进行过滤,这似乎运行得更快,但它不会过滤掉匹配零个ProductShops 文档的产品。所以我们仍然需要在后面的步骤中使用$match 或使用$unwindpreserveNullAndEmptyArrays : false 将它们过滤掉,这会使查询再次变慢。

有没有办法绕过这个限制?

【问题讨论】:

  • 请发布示例数据,我们会尽力帮助调试。

标签: mongodb aggregation-framework aggregation


【解决方案1】:

没有办法绕过这个限制,如果你发布你的聚合,我可以尝试帮助提高效率。

“关系”依赖并不是 Mongo 等非结构化数据库的强项,通常提高查询性能的“最佳实践”是复制数据,这意味着将 category 字段添加到 ProductsShops。如果您习惯于结构化数据库,那感觉“不对”,但在 Mongo 中,这不仅不会令人不悦,而且值得推荐。

这样做时要考虑的一点是您牺牲了“完整性”,这意味着当您更新产品类别时将其同步到其他集合显然不会是原子的,话虽如此,我假设该操作不会经常发生因为产品不会每天都有新的类别。

【讨论】:

    猜你喜欢
    • 2013-09-03
    • 2018-06-18
    • 1970-01-01
    • 2018-02-06
    • 2020-09-24
    • 2020-06-27
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多