简体   繁体   中英

Aggregation issue with Mongo 3.6

I was using the aggregate function without any problem connecting a 3.4 mongodb.

When I change to a 3.6 db,

I've got the message: The 'cursor' option is required, except for aggregate with the explain argument.

Sorry if it's already posted. I am unable to find any solutions

In mongo 3.6 there has been changes while using aggregate you have to use cursor, unless you include the explain option, you must specify the cursor option. I faced same error as you were facing. Now you have to do it like

this.aggregate( [
        { $unwind : "$tags" },
        {$group: {_id: '$tags', count: { $sum: 1} }},
        {$sort: { count: 1 }}
            ] ).cursor({}).exec();

Now you can use cursor method cursor.toArray() to return an array that contains all the documents from a cursor. Cursors returned from aggregation only supports cursor methods that operate on evaluated cursors like cursor.toArray(), to know about more cursor methods you can click here and get further.

In Node.js, after upgrade MongoDB from 3.4 to 3.6, there are 2 things that need to check:

  1. Add cursor: {} option in the aggregate statement. In previous MongoDB version, this is optional (Of course, you can define batchSize in cursor object if you want). For example:

     db.collection(collectionName).aggregate(pipelineArray, { cursor: {} }, function(error, result) { ... });
  2. If the above code hang and the callback is not invoked, please check the mongodb driver version. I get this "not responding" problem in mongodb module v2.2.16. After upgrade mongodb to v2.2.35, it's fixed.

For those with issues trying to figure out a complete example on 3.6, this worked for me :

function aggregateLoad(db, collectionName, lookUpOption, matchOption, callback) {
        var defCursor = {};
        var cursor = db.collection(collectionName).aggregate([
            {
                $lookup: lookUpOption
            },
            {
                $match: matchOption
            }
        ],defCursor,null);
        cursor.toArray(function(err, docs) {
            console.log("Some data: ", docs);
            callback(err, docs);
            db.close();
        });

}

then you can call the above function as :

function testAggregateLoad(someId, callback) {
        var match = {
            "localId": someId
        };
        var aggregateQuery = {
            from: "someSecondCollectionName",
            localField: "localId",
            foreignField: "_id",
            as: "someData"
        };
        getConnection(conCallBackEx);
        function conCallBackEx(db) {
           aggregateLoad(db, "someBaseLoadCollection", aggregateQuery, match, onSuccess);
        }
        function onSuccess(err, json) {
            console.log('Loaded data is ', json);
            callback(json);
        }
    }



function getConnection(callback) {
        var MongoClient = require('mongodb').MongoClient;
        return MongoClient.connect(url, function (err, db) {
            if (null === err) {
                callback(db, err);
            } else {
                console.log("failed to get db connection retrying  " + err);
                getConnection(callback);
            }
        });
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM