【问题标题】:MongoDB query optimisation for nested array of objects针对嵌套对象数组的 MongoDB 查询优化
【发布时间】:2021-03-01 12:17:45
【问题描述】:

我需要有关嵌套对象数组的查询优化方面的帮助。

我们有大量文档的集合,每个文档都包含嵌套的对象数组,最高可达 3 级,如下所示:

集合名称:产品

收集的文件总数:2000 万份

每个文档的大小:>= 500 kb

[
    {
        "_id":"ObjectId('121212')",
        "id":999,
        "name":"prod1",
        "sellers":[
            {
                "seller_id":99,
                "name":"Business 1",
                "providers":[
                    {
                        "seller_id":99,
                        "provider_id":1,
                        "provider_name":"prov 1",
                        "quantity":50,
                        "order_allowed":40,
                        "notification_on_stock":true
                    },
                    {
                        "seller_id":99,
                        "provider_id":2,
                        "provider_name":"prov 2",
                        "quantity":20,
                        "order_allowed":20,
                        "notification_on_stock":true
                    }
                ]
            },
            {
                "seller_id":9,
                "name":"Business 2",
                "providers":[
                    {
                        "seller_id":9,
                        "provider_id":3,
                        "provider_name":"prov 3",
                        "quantity":50,
                        "order_allowed":40,
                        "notification_on_stock":true
                    },
                    {
                        "seller_id":9,
                        "provider_id":4,
                        "provider_name":"prov 4",
                        "quantity":20,
                        "order_allowed":20,
                        "notification_on_stock":true
                    }
                ]
            }
        ]
    },
    {
        "_id":"ObjectId('232323')",
        "id":1000,
        "name":"prod 2",
        "sellers":[
            {
                "seller_id":44,
                "product_id":2,
                "name":"Business 22",
                "providers":[
                    {
                        "seller_id":44,
                        "provider_id":3,
                        "provider_name":"prov 3",
                        "quantity":50,
                        "order_allowed":40,
                        "notification_on_stock":true
                    },
                    {
                        "seller_id":44,
                        "provider_id":4,
                        "provider_name":"prov 4",
                        "quantity":20,
                        "order_allowed":20,
                        "notification_on_stock":true
                    }
                ]
            },
            {
                "seller_id":91,
                "name":"Business 21",
                "providers":[
                    {
                        "seller_id":91,
                        "provider_id":1,
                        "provider_name":"prov 1",
                        "quantity":50,
                        "order_allowed":40,
                        "notification_on_stock":true
                    },
                    {
                        "seller_id":91,
                        "provider_id":2,
                        "provider_name":"prov 2",
                        "quantity":20,
                        "order_allowed":20,
                        "notification_on_stock":true
                    }
                ]
            }
        ]
    },
    {
        "_id":"ObjectId('989798')",
        "id":1001,
        "name":"prod 3",
        "sellers":[
            {
                "seller_id":33,
                "name":"Business 112",
                "providers":[
                    {
                        "seller_id":33,
                        "provider_id":1,
                        "provider_name":"prov 1",
                        "quantity":50,
                        "order_allowed":40,
                        "notification_on_stock":true
                    },
                    {
                        "seller_id":33,
                        "provider_id":2,
                        "provider_name":"prov 2",
                        "quantity":20,
                        "order_allowed":20,
                        "notification_on_stock":true
                    }
                ]
            },
            {
                "seller_id":32,
                "name":"Business 2",
                "providers":[
                    {
                        "seller_id":32,
                        "provider_id":1,
                        "provider_name":"prov 1",
                        "quantity":50,
                        "order_allowed":40,
                        "notification_on_stock":true
                    },
                    {
                        "seller_id":32,
                        "provider_id":2,
                        "provider_name":"prov 2",
                        "quantity":20,
                        "order_allowed":20,
                        "notification_on_stock":true
                    }
                ]
            }
        ]
    }
]

我为我的产品集合添加了以下索引,如下所示,

  1. products.id 上的索引

    { “身份证”:1 }

  2. 嵌套数组文档的索引

    { “products.sellers.seller_id”:1 }

{
    "id":1,
    "sellers.seller_id":1,
    "sellers.providers.provider_id":1
}

我的查询:

db.products.find({
    "id":999,
    "sellers":{
        "$elemMatch":{
            "providers":{
                "$elemMatch":{
                    "seller_id":30098,
                    "provider_id":517
                }
            }
        }
    }
});

我的问题是查询总是获取字段 id 上的第一个索引,并且查询花费了大约 800 毫秒的时间,我需要对其进行优化。

【问题讨论】:

  • 您认为提供的答案中是否有某些内容无法解决您的问题?如果是这样,那么请对答案发表评论,以澄清究竟需要解决哪些尚未解决的问题。如果它确实回答了您提出的问题,请注意Accept your Answers您提出的问题

标签: node.js mongodb mongoose mongodb-query mongodb-nodejs-driver


【解决方案1】:

您的第三个复合索引将显示在拒绝计划中,因为您的条件与您的复合索引不同,

您在provides 中匹配seller_id,但提供索引在selles.seller_id

根据您的要求,我不确定什么是正确的,但请选择以下之一以实现获胜计划中的指标,

  1. 要么你的查询有误,你应该改成这样,
db.products.find({
    "id":999,
    "sellers":{
        "$elemMatch":{
            "seller_id":30098,
            "providers":{
                "$elemMatch":{
                    "provider_id":517
                }
            }
        }
    }
});
  1. 要么你创建了错误的索引,你应该更正它,
{
    "id":1,
    "sellers.providers.seller_id":1,
    "sellers.providers.provider_id":1
}

其次,我注意到您创建了错误的索引,我在您的文档中看不到任何 products 键,

  1. 嵌套数组文档的索引

    { "products.sellers.seller_id":1 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-23
    • 2016-09-05
    • 1970-01-01
    • 2020-03-28
    • 2021-01-24
    • 1970-01-01
    • 2018-11-01
    • 2019-05-17
    相关资源
    最近更新 更多