我的服务器上有 mongodb 版本 3.6。我的服务器源在nodeJS
我有一些这样的文件:
{"title": "test1", sort: 1, parent: 1},
{"title": "test2", sort: 7, parent: 1},
{"title": "test3", sort: 5, parent: 1},
{"title": "test4", sort: 1, parent: 2},
{"title": "test5", sort: 7, parent: 2},
{"title": "test6", sort: 5, parent: 2}
现在我想更新一组文档(例如带有
parent=1
的文档),并按照 previous value plus 10
以数字 1 开头的模式设置该组的排序字段值与新值。
所以我想要下面的结果:
{"title": "test1", sort: 1, parent: 1},
{"title": "test2", sort: 21, parent: 1},
{"title": "test3", sort: 11, parent: 1},
{"title": "test4", sort: 1, parent: 2},
{"title": "test5", sort: 7, parent: 2},
{"title": "test6", sort: 5, parent: 2}
执行此操作的最佳方式和最佳性能是什么?
仅使用 Mongo 3.6 中可用的操作:
由于您一次只想更新一个父级,因此最后一个阶段是
$merge
。并且文档仅包含原始 _id
和新 sort
的字段。
db.collection.aggregate([
{
// match on the parent you want
$match: { "parent": 1 }
},
{
// sort the docs under that parent
$sort: { "sort": 1 }
},
{
// create a group for that one parent which is
// currently all docs due to first $match stage
$group: {
_id: null,
docs: {
// docs will be already sorted in this array
$push: "$$ROOT"
}
}
},
{
// set each doc `sort` field to the value it should be
// based on its index in docs
$set: {
docs: {
$map: {
input: "$docs",
in: {
"_id": "$$this._id",
"sort": {
$add: [
1,
{
$multiply: [
{ $indexOfArray: ["$docs", "$$this"] },
10
]
}
]
}
}
}
}
}
},
{ $unwind: "$docs" },
{ $replaceRoot: { newRoot: "$docs" } },
{ $merge: "collection" }
])
如果您想查看完整的结果文档是什么,请参阅这个类似的管道。主要区别是
$map
阶段的 $set
部分,其中包括所有文档字段。您还可以添加最后一个 { $merge: "collection" }
阶段来按原样使用此管道。但既然您询问了性能,那么合并应该只包含更新的字段,而不是完整的文档。
顺便说一句,为了性能,最好将更新应用于所有文档,而不必每次都设置父文档。即更新
每个父组的所有文档的
sort
值。
$setWindowFields
可用,那么这适用:
与您的相关的先前问题相比,此答案所需的更改相当小,我的答案。
使用 $rank
的
$setWindowFields
功能提供排名 1、2、3 等,这将基于现有 sort
值。
partitionBy
添加 parent
,以便每个分区(组)由父分区分隔。最终的新排序将是
(rank - 1) x 10 + 1
使用
$out
操作将所有更新的文档写回到同一个集合中。
唯一的变化是在
partitionBy: "$parent"
中添加了 $setWindowFields
:
db.collection.aggregate([
{
$setWindowFields: {
partitionBy: "$parent",
sortBy: { sort: 1 },
output: {
sort: { $rank: {} }
}
}
},
{
$set: {
sort: {
$add: [
1,
{
$multiply: [
{ $subtract: ["$sort", 1] },
10
]
}
]
}
}
},
{ $out: "collection" }
])