我想在 MongoDB 中创建一个物化 View ,并弄清楚除了一部分之外的大部分内容(这很关键)。
用例: 我有一个记录列表,它们本质上是动态的(每天更新或根据用户的操作更新)
例如。我们称之为EmployeeSalary
{
'month': 'jan',
'employee_id': 1,
'duration': 15, (days)
'salary': 1000 (USD),
'client_id': 'c1'
}
{
'month': 'jan',
'employee_id': 2,
'duration': 15, (days)
'salary': 1500 (USD),
'client_id': 'c2'
}
等等..
我想在 salary
属性上创建一个物化 View ,这很简单。这里的结果将是 2500
但现在的问题是:这些记录可能会改变。例如,如果id
:1
的员工的工资从1000
更改为2000
,那么我希望物化 View 具有更新的值,即从 2500
到 3500
基本上,它应该类似于OldAggregateValue - oldRecordValue + newRecordValue
=> 2500 - 1000 + 2000 = 3500
有没有办法只更新该记录的值而不是再次总结所有内容?这在这里很重要,因为我有近 25,000 条此类记录,而且这是为多个客户完成的。我需要这个操作尽可能高效。
我已经阅读了 mongo 的官方文档,但他们在提供的示例中没有提到这一点( On-Demand Materialized View: Update/Replace Data )他们只是提到了在输出集合中更新/插入。
任何指示将不胜感激。
最佳答案
不确定您是否找到了您正在寻找的答案,但我刚刚完成了一项功能,该功能使用由变更流提供的按需物化 View 来计算和发出实时状态更新。我的 View 不断更新,并且随着收到更改而增加记录是有效执行此操作的唯一方法。
我关注了this article和 this section Mongo 的《聚合》一书作为指南 - 两者对于思考不同的用例和实现都非常有帮助。
总而言之,要处理增量操作,您需要设置一个用于处理数据子集的管道。上面的示例在 $match
阶段使用时间戳来限制正在处理的记录。就我而言,尝试使用时间戳并处理来自变更流的多个变更事件太困惑了,我最终使用 _id
来确保我准确地捕获每个事件一次。
为了更改 View ,我在合并阶段使用了自定义 $project
管道来规定匹配文档时 $merge
阶段的行为。最后,我的 $merge
阶段看起来像:
const mergeStage = {
$merge: {
into: 'demo-view',
on: '_id',
whenMatched: [{
$project: {
aggregate: "$total",
increment: "$$new.total",
total:{$sum: ["$total", "$$new.total"]}, // instead of replace the document, this $project pipeline increments the total when the document exists
other_property: 1,
_id: 1,
}
}],
whenNotMatched: "insert"
}}
这表明文档在匹配时应递增,但如果未找到匹配项,则应插入新文档。您需要根据您的特定目的进行自定义,但我发现这对于我的代码来说是一个很好的模板。
关于MongoDB物化 View -如何增量更新输出结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72516907/