ozomer / node-red-contrib-mongodb2

MongoDB driver node for Node-RED
Apache License 2.0
15 stars 19 forks source link

aggregate.toArray not working as expected #4

Closed brunnels closed 8 years ago

brunnels commented 8 years ago

I checked npm and I'm using version 0.2.2.

I am able to get this working using the collection operation on the mongodb2 node and it returns 3 records as expected.

When I try the same aggregate using Dynamic (msg.operation) aggregate.toArray I get output that looks similar to find.toArray and no aggregation looks to be happening. The payload array objects have the original columns rather than the ones defined in the aggregate group and all records in the collection are returned.

Working using collection operation

 var coll = msg.payload;
 var agr = coll.aggregate([
     { $sort: { date: 1}},
     { $group: { 
         _id: '$topic',
         value: { $last: "$value"},
         lastDoc: { $last: "$_id"}
     } }
 ]).toArray(function(err, results) {
     var newMsg = {};

     results.forEach(function(result) {
        var time = result.lastDoc.getTimestamp()
        time.setHours(time.getUTCHours() - 6);
        newMsg[result._id] = {
            value: result.value,
            time: time.toLocaleString()
        };
     });

     node.send(newMsg);
 });

Not working Dynamic (msg.operation)

var newMsg = {};
newMsg.operation = 'aggregate.toArray';
newMsg.collection = 'temps';
newMsg.payload = [
    { $sort: { date: 1}},
    { $group: { 
        _id: '$topic',
        value: { $last: "$value"}
    } }
];
return newMsg;

handler function

var newMsg =[];
for (var i = 0; i < msg.payload.length; i++) {
    var item = {};
    var time = msg.payload[i].lastDoc.getTimestamp()
    time.setHours(time.getUTCHours() - 6);
    item[msg.payload[i]._id] = { 
        value: msg.payload[i].value,
        time: time.toLocaleString()
    };
    newMsg.push(item);
};
return  {payload: newMsg};
ozomer commented 8 years ago

Please have a look at the aggregate function in node-mongodb-native. It receives two arguments: pipeline and options (and a callback). So msg.payload should be an array of two values:

So you should write something like:

var pipeline = [
    { $sort: { date: 1}},
    { $group: { 
        _id: '$topic',
        value: { $last: "$value"}
    } }
];
msg.payload = [pipeline, null];

I am not sure, but maybe writing msg.payload = [pipeline]; will also do the job. Let me know if it works!

brunnels commented 8 years ago

Yes, that worked. Thank you for your assistance!. msg.payload = [pipeline]; was sufficient.

roalcantara commented 7 years ago

Hi there!

I dunno why, but I could only get this working by sending an array with two values. That is:

pipeline = {
  "$group": {
    "_id": "$regra",
    "docId": { "$first": "$_id" }
  }
};
msg.payload = [pipeline, null]; //this woks!

msg.payload = [pipeline]; //this doesn't! :(

Am I doing something wrong?

ozomer commented 7 years ago

Please see the aggregate function. It receives 3 parameters: pipline, options, callback. So msg.payload should be an array of two elements: [piplline, options].

I think the proper way in your case should be msg.payload = [pipeline, {}]; (unless you want to use other non-default options). It seems like the function also accepts null for the options parameter, but it must be there.