MongoDB Shema 支持文档的并发更新
MongoDB Shema to support concurrent update on a document
我们正在处理一个包含 300 个文档的项目,主 currentValue
字段在 collection 中,以便跟踪第一个 collection 的每个文档的历史记录。我们创建了另一个名为 history
的 collection,其中包含大约 650 万份文档。
对于系统的每个输入,我们必须添加大约 30 个历史项并更新主 collection 的 currentValue
字段,因此,我们尝试了 currentValue
的计算字段设计模式,这导致我们有 writeConfilict
在并发情况下(并发约 1000 个请求)。
然后我们尝试用 sum
(amount
字段)和 groupBy
(mainId
字段)计算 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
}
我们正在处理一个包含 300 个文档的项目,主 currentValue
字段在 collection 中,以便跟踪第一个 collection 的每个文档的历史记录。我们创建了另一个名为 history
的 collection,其中包含大约 650 万份文档。
对于系统的每个输入,我们必须添加大约 30 个历史项并更新主 collection 的 currentValue
字段,因此,我们尝试了 currentValue
的计算字段设计模式,这导致我们有 writeConfilict
在并发情况下(并发约 1000 个请求)。
然后我们尝试用 sum
(amount
字段)和 groupBy
(mainId
字段)计算 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
}