MongoDB Shema 支持文档的并发更新

MongoDB Shema to support concurrent update on a document

我们正在处理一个包含 300 个文档的项目,主 currentValue 字段在 collection 中,以便跟踪第一个 collection 的每个文档的历史记录。我们创建了另一个名为 history 的 collection,其中包含大约 650 万份文档。 对于系统的每个输入,我们必须添加大约 30 个历史项并更新主 collection 的 currentValue 字段,因此,我们尝试了 currentValue 的计算字段设计模式,这导致我们有 writeConfilict 在并发情况下(并发约 1000 个请求)。

然后我们尝试用 sumamount 字段)和 groupBymainId 字段)计算 currentValue 字段 collection 花费的时间太长(> 3 秒)。

主要 collection 文档:

{
    "_id" : ObjectId(...),
    "stock" : [ 
        {
            "currentAmount" : -313430.0,
            "lastPrice" : -10.0,
            "storage" : ObjectId("..."),
            "alarmCapacity" : 12
        }, 
        {
            "currentAmount" : 30,
            "lastPrice" : 0,
            "storage" : ObjectId("..."),
            "alarmCapacity" : 12
        }, 
       .
       .
       .
    ],
    "name" : "name",

}


历史collection 文档:

{
    "_id" : ObjectId("..."),
    "mainId" : ObjectId("..."),
    "amount" : 5,
}

如果您有任何其他想法来处理这种情况(应用程序或数据库级别),我将不胜感激。

更新 1

如果我使用计算模式,更新查询将是:

mainCollection.findOneAndUpdate(
            {
                $and: [
                    { _id: id },
                    { "stock.storage": fromId },
                    { "stock.deletedAt": null }
                ],
            },
            {
                $inc: {
                    "stock.$.currentAmount": -1 * amount,
                }
            },
            {
                session
            }
        )

如果我想每次都计算 currentAmount 和聚合管道:

mainCollection.aggregate([
            {
                $match: { 
                    branch: new ObjectId("...")
                }
            },
            {
                $group: {
                    _id: "$ingredient",
                    currentAmount: {
                        $sum: "$amount"
                    }
                }
            }])

为了有计算域,mongo设计模式,建议computed field

The Computed Pattern is utilized when we have data that needs to be computed repeatedly in our application. link

如下所示:

// your main collection will look like this
{
    "_id" : ObjectId(...),
    "stock" : [ 
        {
            "currentAmount" : -313430.0,
            "lastPrice" : -10.0,
            "storage" : ObjectId("..."),
            "alarmCapacity" : 12
        }, 
        {
            "currentAmount" : 30,
            "lastPrice" : 0,
            "storage" : ObjectId("..."),
            "alarmCapacity" : 12
        }, 
    "totalAmount": 20000 // for example
}

但是对于并发有一个更好的方法来解决这个问题cumulative summation,在这个算法中,我们将最后的文档输入与当前输入相加:

{
    "_id" : ObjectId("..."),
    "mainId" : ObjectId("..."),
    "amount" : 5,
    "cumulative": 15 // sum of last documents input
}