【问题标题】:Optimization of query for nested arrays嵌套数组查询优化
【发布时间】:2019-06-22 06:24:45
【问题描述】:

我的mongodb数据库结构如下:

[{"_id" : 1,
"main_array" : [{"subid" : 11,"date" : 2019-01-01,"details":[somearray]},
                {"subid" : 12,"date" : 2019-01-02,"details":[somearray]},
                {"subid" : 13,"date" : 2019-01-03,"details":[somearray]}]
},
{"_id" : 2,
"main_array" : [{"subid" : 21,"date" : 2019-01-01,"details":[somearray]},
                {"subid" : 22,"date" : 2019-01-02,"details":[somearray]},
                {"subid" : 23,"date" : 2019-01-03,"details":[somearray]}]
},
{"_id" : 3,
"main_array" : [{"subid" : 31,"date" : 2019-01-01,"details":[somearray]},
                {"subid" : 32,"date" : 2019-01-02,"details":[somearray]},
                {"subid" : 33,"date" : 2019-01-03,"details":[somearray]}]
}
]

“_id”代表user_id。文档随着用户的增加而增加。 “主数组”就像一个日志,其中包含每个用户每天的条目。我对某一天在场的所有用户的“详细信息”数组感兴趣。

我使用以下查询成功获得了结果:

dbase.collection("user_log").aggregate([
        {$unwind : "$main_array"},
        {$match : {"main_array.date" :2019-01-01}},
      ])

我怀疑这是我的查询优化了吗?由于我在管道的第一阶段使用 unwind,它可能会创建太多文档。当我的数据库大小增加时,这会是一个问题吗?或者有什么优化的方法吗?

我也对重组数据库的想法持开放态度(如果对重组提出建议,请说明当前模型可能出现的问题)。

【问题讨论】:

    标签: node.js mongodb query-optimization


    【解决方案1】:

    以下数据模型可以帮助您高效地运行所需的查询,而无需聚合查询:

    数据模型:

     [{
                "_id": ObjectId(),
                "user_id": 1,
                "subid": 11,
                "date": 2019 - 01 - 01,
                "details": [somearray]
            },
            {
                "_id": ObjectId(),
                "user_id": 1,
                "subid": 12,
                "date": 2019 - 01 - 02,
                "details": [somearray]
            },
            {
                "_id": ObjectId(),
                "user_id": 1,
                "subid": 13,
                "date": 2019 - 01 - 03,
                "details": [somearray]
            },
            {
                "_id": ObjectId(),
                "user_id": 2,
                "subid": 21,
                "date": 2019 - 01 - 01,
                "details": [somearray]
            },
            {
                "_id": ObjectId(),
                "user_id": 2,
                "subid": 22,
                "date": 2019 - 01 - 02,
                "details": [somearray]
            }
        ]
    

    查询:

    我对显示在 a 上的所有用户的“详细信息”数组感兴趣 特定的日子。 以下查询将返回用户一天的详细信息:

    db.collection.find({user_id:1, date:2019 - 01 - 01})
    

    这将避免对大型集合和展开阶段进行聚合。 您可以使用此数据模型避免嵌套数组操作。

    如果您想在以后执行特定于用户的聚合,您可以使用$match 作为聚合管道的第一阶段。这将帮助您拥有optimized pipeline

    索引:

    1. 您可能需要创建唯一索引以避免用户一天的重复记录。
    2. 确保您有正确的索引来提供基本的查找操作。例如 {user_id:1, date:1} 在这种情况下

    【讨论】:

    • 你能解释一下当前数据结构和我使用的查询的问题吗?
    • 1.除非经过优化,否则在大规模使用 $unwind 时,聚合可能会很昂贵。 2. 要获取用户一天的简单详细信息,您需要在整个集合上建立一个大型聚合管道
    • 是否可以每天为每个用户添加不同的文档?在这种情况下,随着用户数量的增加,每天都会插入大量文档。
    • 同意。使用这种方法,您将能够为每位用户每年存储 1095(356*3) 个(注意:3 是假定的 subid 数)文档。当您的集合变得很大时,您可以使用 TTL 使旧文档过期。 2. 如果集合的大小变得非常大(可扩展),您可以对集合进行分片 3. 您可以将 90 天后的数据归档到离线存储(如果它们将来可能使用)
    • 使用这个查询怎么样? ` dbase.collection("user_log").aggregate([ { $project: { 'filteredValue': { $filter: { input: "$main_array", as: "someObj", cond: { $eq: [ '$$ someObj.date',2019-01-01 ] } } } } }`
    猜你喜欢
    • 2018-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多