合并并聚合具有相同架构mongodb的两个或多个集合的某些字段

Merge and aggregate some fields of two or more collections with identical schema mongodb

本文关键字:两个 集合 字段 合并 mongodb      更新时间:2023-09-26

我有一些具有相同架构的集合,我想对它们执行合并+聚合。模式很简单,如下所示:

{ 'fr': 1, 'to': 1, 'wg': 213}
{ 'fr': 1, 'to': 2, 'wg': 53}
{ 'fr': 2, 'to': 2, 'wg': 5521}

以下代码适用于合并两个集合,但我想知道是否有更快的解决方案和/或可以以类似的方式合并多个集合而不创建嵌套调用的解决方案:

var c = db.collection('first').find()
c.each(function(err, doc) {
    if (err) throw err
    if (doc == null) {
        console.log('done')
        return
    }
    db.collection('second').findOne({
        'fr': doc['fr'],
        'to': doc['to']
    }, function(err, doc2) {
        if (err) throw err
        db.collection('my_results').save({
            'fr': doc['fr'],
            'to': doc['to'],
            'wg': doc['wg'] + doc2['wg']
        }, function(err) {
            if (err) throw err
        })
    })
})

这里没有绝对免费的操作,因为您无法使用MongoDB进行联接。但是您可以使用mapReduce及其一些功能来获得您想要的输出。

因此,首先创建一个映射器:

var mapper = function () {
  emit( { fr: this.fr, to: this.to }, this.wg )
};

然后是一个减速器:

var reducer = function (key,values) {
  return Array.sum( values );
};

然后运行mapReduce操作,并将输出设置为不同的集合:

db.first.mapReduce(mapper,reducer,{ "out": { "reduce": "third" } })

请注意此处的"out"选项,本手册部分对此进行了解释。重点是,尽管控制台中输出的统计数据可能会产生误导,但"reduce"语句非常重要。当我们对另一个集合运行相同的代码时,情况就是这样:

db.second.mapReduce(mapper,reducer,{ "out": { "reduce": "third" } })

结果中实际发生的是,第一次操作的输出也被传递到第二次操作的"减少"阶段。

最终结果是,具有相同键值的两个集合中的所有值都将被添加到"第三个"集合中:

{ "_id" : { "fr" : 1, "to" : 1 }, "value" : 426 }
{ "_id" : { "fr" : 1, "to" : 2 }, "value" : 106 }
{ "_id" : { "fr" : 2, "to" : 2 }, "value" : 11042 }

如果您希望frto是两种可能性的唯一组合,或者甚至运行另一个mapReduce或对这些结果进行聚合,那么您可以让它变得更花哨一些。