apdm
apdm

Reputation: 1330

How can I find all documents with a matching ID using an array of another object?

I have 2 models, Alarm and Alert.

The AlertSchema has a created_byfield which references an Alarm object id.

Given an array of Alarmobjects, how can I find all corresponding alerts?

This doesn't work (I wasn't really expecting it to)

// Get array of alarm objects
Alarm.find({unit: req.unit._id}).exec(function(err, alarms){
   // Use array of alarm objects to find all alerts
   Alert.find({created_by: alarms})

Is my best bet to extract the _id from each object into an array and pass that as an argument like this:

    Alarm.find({unit: req.unit._id}).exec(function(err, alarms){
   var alarm_ids = alarms.map(function(o){return o._id});
   // Use array of alarm objects to find all alerts
   Alert.find({created_by: alarm_ids})

Upvotes: 1

Views: 39

Answers (1)

chridam
chridam

Reputation: 103445

You can actually use the aggregation framework and query using the $lookup operator that makes it possible to do a left outer join on to the other collection.

Check the following example:

Alarm.aggregate([
    { "$match": { "unit": req.unit._id } },
    {
        "$lookup": {
            "from": "alerts",
            "localField": "_id",
            "foreignField": "created_by",
            "as": "alarm_alert"
        }
    },
    { "$unwind": "$alarm_alert "}
]).exec(function(err, result){
    console.log(JSON.stringify(result, null, 4));
});

The above is efficient since it's an atomic query and uses the native operators.


Going with your solution attempt, you were missing the $in operator as the final fit to your jigsaw puzzle but one thing that puts the fly in the celebration ointment is the fact that you are making repeated calls to the server i.e. one to retrieve the alarm objects and another to query the alerts collection hence it may not be as efficient as the above aggregate operation:

Alarm.find({ "unit": req.unit._id })
      .lean() // <-- return plain javascript objects
      .exec(function(err, alarms){
            var alarm_ids = alarms.map(function(o){return o._id});
            // Use array of alarm objects to find all alerts
            Alert.find({ "created_by": { "$in": alarm_ids } }).exec(callback);
       });

Upvotes: 1

Related Questions