如何在不将集合替换为其他聚合输出的情况下将MongoDB聚合的结果输出到集合中?
我只需要使用$ out:'tempCollection'来获取数据,因为我有500万个文档,并获得pipeline stage limit
var q = [
{$match: query},
{$group: {_id: '$hash'}},
{$out: 'tempCollection'}
];
async.parallel([
function(callback) {
firstCollection.aggregate(q, callback);
},
function(callback) {
secondCollection.aggregate(q, callback);
},
...
], function() {
// I want to get all from tempCollection (with pagination) here
});
答案 0 :(得分:1)
这里的底线是$out
选项只能“替换”目标集合上的输出。所以要做其他事情,你必须通过客户端连接,而不是只输出到服务器。
此处使用mongoose的最佳选择是直接进入底层驱动程序并访问驱动程序支持的node stream interface。
Trival示例,但它显示了构造的基本方法:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/aggtest');
var testSchema = new Schema({},{ "_id": false, strict: false });
var ModelA = mongoose.model( 'ModelA', testSchema ),
ModelB = mongoose.model( 'ModelB', testSchema ),
ModelC = mongoose.model( 'ModelC', testSchema );
function processCursor(cursor,target,callback) {
cursor.on("end",callback);
cursor.on("error",callback);
cursor.on("data",function(data) {
cursor.pause();
target.update(
{ "_id": data._id },
{ "$setOnInsert": { "_id": data._id } },
{ "upsert": true },
function(err) {
if (err) callback(err);
cursor.resume();
}
);
});
}
async.series(
[
// Clean data
function(callback) {
async.each([ModelA,ModelB,ModelC],function(model,callback) {
model.remove({},callback);
},callback);
},
// Sample data
function(callback) {
async.each([ModelA,ModelB],function(model,callback) {
async.each([1,2,3],function(id,callback) {
model.create({ "_id": id },callback);
},callback);
},callback);
},
// Run merge
function(callback) {
async.parallel(
[
function(callback) {
var cursor = ModelA.collection.aggregate(
[
{ "$group": { "_id": "$_id" } }
],
{ "batchSize": 25 }
);
processCursor(cursor,ModelC,callback)
},
function(callback) {
var cursor = ModelB.collection.aggregate(
[
{ "$group": { "_id": "$_id" } }
],
{ "batchSize": 25 }
);
processCursor(cursor,ModelC,callback)
}
],
callback
);
},
// Get merged
function(callback) {
ModelC.find({},function(err,results) {
console.log(results);
callback(err);
});
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
Oustide,那么你将需要$out
来“分离”集合,然后将它们与类似的.update()
进程合并,但要保持它“服务器端”,那么你需要使用.eval()
。
这不好,但这是在服务器上保持操作的唯一方法。您还可以使用"Bulk"操作(再次通过相同的本地.collection
接口)对此进行修改,以获得更高的吞吐量。但选项归结为“通读客户端”或“评估”。