在基于文档的聚合管道中使用 $merge 不起作用

Posted

技术标签:

【中文标题】在基于文档的聚合管道中使用 $merge 不起作用【英文标题】:Using $merge in Document-based aggregation pipeline is not working 【发布时间】:2021-11-29 22:40:29 【问题描述】:

我有一个集合,我想对其执行聚合并将结果放入同一数据库中的单独集合中。在仔细检查文档时,我偶然发现了$merge,它完全符合我的要求。我想出了以下 mongo shell 管道,它可以完美运行。

db.getCollection('SOURCE_COLLECTION').aggregate([
  
    "$match": type: 'ABC'
  ,
  
    "$merge": 
      "into": "OUTPUT_COLLECTION",
      "whenMatched": "replace"
    
  
])

现在,我需要在 Spring boot 中实现同样的效果,为此我想出了以下方法,理论上应该没有什么不同。

final ArrayList<Document> pipeline = new ArrayList<>();

pipeline.add(Document.parse("$match: type: 'ABC'"));
pipeline.add(Document.parse("$merge: into: 'OUTPUT_COLLECTION', whenMatched: 'replace'"));

mongoTemplate.getDb()
    .getCollection("SOURCE_COLLECTTION", Document.class)
    .aggregate(pipeline);

不过,这行不通。可以看出,我正在使用MongoCollection&lt;T&gt;.aggregate() 方法,它将List&lt;Document&gt; 作为管道。管道中的每个阶段都是通过将 JSON 字符串解析为文档来生成的。

有趣的是,当我将合并替换为 $out 时,它可以正常工作。

final ArrayList<Document> pipeline = new ArrayList<>();

pipeline.add(Document.parse("$match: type: 'ABC'"));
pipeline.add(Document.parse("$out: 'OUTPUT_COLLECTION'"));

mongoTemplate.getDb()
    .getCollection("SOURCE_COLLECTTION", Document.class)
    .aggregate(pipeline);

但这对我没有好处,因为这个聚合将被执行多次(实际上我试图在这里填充一个物化视图类型的集合)。我需要$merge 才能工作,但它不需要。我错过了什么?有人能看到我没有看到的东西吗?

【问题讨论】:

【参考方案1】:

当在管道中使用$merge 时,方法aggregate(pipeline) 的行为看起来不像终端操作。为了使合并工作,应该调用一些像void toCollection()void forEach(Consumer&lt;? extends T&gt; consumer) 这样的操作。因此,在从 aggregate() 返回时调用 toCollection() 就可以了。

final ArrayList<Document> pipeline = new ArrayList<>();

pipeline.add(Document.parse("$match: type: 'ABC'"));
pipeline.add(Document.parse("$out: 'OUTPUT_COLLECTION'"));

mongoTemplate.getDb()
    .getCollection("SOURCE_COLLECTTION", Document.class)
    .aggregate(pipeline)
    .toCollection(); // This invocation completes the pipeline when it ends with $merge.

有趣的是,在文件中似乎没有提到这种类型(至少在我能找到的任何文件中都没有)。我不确定这是否是预期的行为。

【讨论】:

以上是关于在基于文档的聚合管道中使用 $merge 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥在与数组中的字段匹配时,mongoDB聚合中的查找中的管道不起作用?

查找聚合中的管道在 mongodb 中不起作用

日期范围在聚合管道中不起作用,但在 find() 中起作用

在聚合查找匹配表达式中引用 root _id 不起作用

在聚合管道中设置条件在 mongodb 中不起作用

mongodb聚合命令