MongoDB物化 View -如何增量更新输出结果?

标签 mongodb mongodb-query aggregation-framework

我想在 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 具有更新的值,即从 25003500

基本上,它应该类似于OldAggregateValue - oldRecordValue + newRecordValue => 2500 - 1000 + 2000 = 3500

有没有办法只更新该记录的值而不是再次总结所有内容?这在这里很重要,因为我有近 25,000 条此类记录,而且这是为多个客户完成的。我需要这个操作尽可能高效。

我已经阅读了 mongo 的官方文档,但他们在提供的示例中没有提到这一点( On-Demand Materialized View: Update/Replace Data )他们只是提到了在输出集合中更新/插入。

任何指示将不胜感激。

最佳答案

不确定您是否找到了您正在寻找的答案,但我刚刚完成了一项功能,该功能使用由变更流提供的按需物化 View 来计算和发出实时状态更新。我的 View 不断更新,并且随着收到更改而增加记录是有效执行此操作的唯一方法。

我关注了this articlethis 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/

相关文章:

node.js - 通过 _id nodejs mongodb native 查找 mongodb 文档

mongodb - Dataloader 没有返回相同长度的数组?

node.js - Mongoose/MongoDb 收到错误 geoNear 不是函数

mongodb - 从 channel 读取 SIGSEGV : segmentation violation

mongodb 在 $filter 中使用投影

java - 在java中将包括$cond的聚合转换为DBObject

mongodb - 查找数组中的最大元素

mongodb - 在保留根字段的同时对子文档进行分组/计数

mongodb - 聚合来自两个数组的 $sum 值

聚合中的 Mongodb 子查询