Ahmed Haque
Ahmed Haque

Reputation: 7514

Mongoose Aggregate Field Results into Array

I'm currently using the following code to sift through two separate collections. One collection holds a total list of messages sent to users. The second collection holds all responses that have come from users.

From the first collection, I'm building an array of messages sent -- then querying the second collection to search for all responses that don't have a match within that array.

Two questions:

1) Is there a better way of outputting Mongoose/MongoDB results into an array than the for loop approach I am using?

2) Is there a better way to compare these collections than I'm using?

// Find all responses (read) messages associated with a patient.
Response.find({patientID: patientID}, function(err, responses){

    // Store all msgIDs into an array.
    for (var i = 0; i < responses.length; i++){
        openedArray.push(responses[i].msgID);
    }

    // Find all messages associated with that same patient, but that were not included in the response list
    Message.find({patientList: patientID, msgID: { $ne: openedArray}}, function(err, unopenedMessages){

        // Store all msgIDs into an array.
        for (var j = 0; j < unopenedMessages.length; j++){
            unopenedArray.push(unopenedMessages[j].msgID);
        }

        // Output a list of unopened messages (msgIDs) and a count of total unread messages
        res.json({unread: unopenedArray, count: unopenedArray.length})
   });
});

Upvotes: 0

Views: 216

Answers (1)

Blakes Seven
Blakes Seven

Reputation: 50406

You can use .distinct() as well as maybe some usage of async.waterfall to clean up the nesting a little:

async.waterfall(
    [
        function(callback) {
            Response.distinct("msgID",{ "patientID": patientID },callback);
        },
        function(opened,callback) {
            Message.distinct(
                "msgID",
                {
                    "patientList": patientID,
                    "msgID": { "$nin": opened }
                },
                callback
            );
        }
    ],
    function(err,unopened) {
        // maybe handle error
        res.json({ "unopened": unopened, "count": unopened.length });
    }
);

Also you likely want $nin for the comparison of the list returned against the field in the second collection.

The waterfall passes the result from each async call to the next stage, which means you don't need to nest each call within the other, so it looks a bit cleaner.

Upvotes: 1

Related Questions