通过相似的对象值使用 findOneAndUpdate 更新对象

Update objects with findOneAndUpdate by similar object value

我正在尝试更新文档值,如果它们已经存在于集合中,如果它们对于特定对象键具有相同的值。

比如我有以下文件-

{ eventType: "A", browsers: [ { name: "Chrome", count: 10 } ]}
{ eventType: "B", browsers: [ { name: "Chrome", count: 2 } ]}
{ eventType: "A", browsers: [ { name: "Chrome", count: 5 }, { name: "Safari", count: 8 } ]}

最后,我希望集合按事件类型合并文档,并按浏览器名称值合并浏览器聚合(在下面的示例中,“Chrome”计数合并为 15) ;如果值不存在,将新对象添加到 browsers 数组(在下面的示例中,将“Safari”对象添加到现有浏览器聚合):

{ eventType: "A", browsers: [ { name: "Chrome", count: 15 }, { name: "Safari", count: 8 } ]}
{ eventType: "B", browsers: [ { name: "Chrome", count: 2 } ]}

如果需要,我想使用以下查询来更新和插入新文档,但我不确定如何进行浏览器聚合。

const doc = { eventType: "A", browsers: [ { name: "Chrome", count: 5 }, { name: "Safari", count: 8 } ]}

collection.findOneAndUpdate({
    eventType: doc.eventType
  }, {

    // What to do in here?

  }, {
    upsert: true,
    new: true
  })

是否有使用自定义函数的选项,例如 collection.aggregate 用例中的 $accumulator

P.S - 我在这段代码中使用猫鼬

不可能在一条语句中执行此操作,因为您的目标是通过 eventType 将文档收集到一组新文档中,但是您可以通过合并聚合来完成大部分工作:

[{$unwind: {
 path: '$browsers',
 includeArrayIndex: 'b',
 preserveNullAndEmptyArrays: true
}}, {$group: {
 _id: '$eventType',
 eventType: {
  $first: '$eventType'
 },
 browsers: {
  $addToSet: '$browsers'
 }
}}, {$addFields: {
 grouped: 1
}}, {$merge: {
 into: 'so_example',
 on: '_id',
 whenMatched: 'replace',
 whenNotMatched: 'discard'
}}]

这将需要第二个过程来 a) 删除未合并的文档和减少浏览器数组的内容,以便每个浏览器都有计数的总和。

显然,不可能在单个原子查询中执行此类操作。 我 'solved' 通过更改模式来实现,因此键将是动态的,例如

{
  browsers: {
    Chrome: {
      count: 15
    }
  }
}

使用此实现,我根据必须插入的新文档动态构建 findOneAndUpdate 的 update 部分。