我可以在MongoDB中批量聚合吗?

时间:2018-02-22 16:32:17

标签: mongodb aggregation-framework

我有一些只读聚合管道,必须并行运行,只有一个连接可用。这可能吗或Mongo只允许查找,批量更新操作但不能聚合?

1 个答案:

答案 0 :(得分:1)

Mongodb驱动程序使用连接池并异步执行聚合命令。除了确保应用程序在执行下一个查询之前不等待响应之外,您不需要做任何特殊操作。

考虑一个测试集合:

mgeneratejs '{"num": {"$integer": {"min": 1, "max": 20}}, "text": {"$paragraph": {sentences: 5}}}' -n 100000 | mongoimport -d so -c text

单个聚合查询

db.text.aggregate([
    {$match: {text: /ert.*duv/i}}, 
    {$group:{_id:null, cnt:{$sum:1}, text:{$push: "$text"}}}
]);

需要大约400毫安。

并行运行其中10个(javascript):

const started =  new Date().getTime();
let db;

MongoClient.connect(url, {poolSize: 10})
    .then(cl =>{
        db = cl.db('so');
        return Promise.all([/ert.*duv/i, /kkd.*aql/i, /zop/i, /bdgtter/i, /ppa.*mcm/i, /ert.*duv/i, /kkd.*aql/i, /zop/i, /bdgtter/i, /ppa.*mcm/i]
            .map(regex=>([{$match: {text: regex}}, {$group:{_id:null, cnt:{$sum:1}, text:{$push: "$text"}}}]))
            .map(pipeline=>db.collection('text').aggregate(pipeline).toArray()))
    })
    .then(()=>{db.close(); console.log("ended in " + ( new Date().getTime() - started))});

需要1,883毫秒(javascript时间),其中~1830是数据库端:

db.getCollection('system.profile').find({ns:"so.text", "command.aggregate": "text"}, {ts:1, millis:1})

{
    "millis" : 442,
    "ts" : ISODate("2018-02-22T17:32:39.738Z")
},
{
    "millis" : 452,
    "ts" : ISODate("2018-02-22T17:32:39.747Z")
},
{
    "millis" : 445,
    "ts" : ISODate("2018-02-22T17:32:39.756Z")
},
{
    "millis" : 471,
    "ts" : ISODate("2018-02-22T17:32:39.762Z")
},
{
    "millis" : 448,
    "ts" : ISODate("2018-02-22T17:32:39.771Z")
},
{
    "millis" : 491,
    "ts" : ISODate("2018-02-22T17:32:39.792Z")
},
{
    "millis" : 566,
    "ts" : ISODate("2018-02-22T17:32:39.854Z")
},
{
    "millis" : 561,
    "ts" : ISODate("2018-02-22T17:32:39.856Z")
},
{
    "millis" : 1822,
    "ts" : ISODate("2018-02-22T17:32:41.118Z")
},
{
    "millis" : 1834,
    "ts" : ISODate("2018-02-22T17:32:41.124Z")
}

如果你进行数学计算,你会看到所有10个在2018-02-22T17:32:39.300Z的同一时间开始,而mongostat在脚本执行时确实显示了10个以上的连接。

poolSize限制为5会使时间加倍,因为请求将分两批执行5次。

驱动程序每个连接使用大约1Mb RAM,因此每个工作者100个连接不是不真实的。

总结 - 确保正确配置连接池,检查实际使用的连接数运行时,检查是否在应用程序级别异步处理请求。