Best way to filter documents on mongodb using properties from another collection

I am trying to filter a document on mongodb using a property from another collection, but the problem is that I need to get all the objects first and then make a filter. Here is my current situation:

Current data:

/* Message collection */
/* 1 */
{
    "_id" : ObjectId("571063533e41b42c2753828a"),
    "user" : ObjectId("570ae3d0a27d4cd44730fc38"),
    "text" : "First text",
    "enabled" : true,
    "deleted" : false,
    "__v" : 0
}

/* 2 */
{
    "_id" : ObjectId("5712a9be27adcff81ea5a39f"),
    "user" : ObjectId("5f236vgh74de563swer120rt"),
    "text" : "Second text",
    "deleted" : false,
    "enabled" : true,
    "__v" : 0
}

/* User collection */
/* 1 */
{
    "_id" : ObjectId("570ae3d0a27d4cd44730fc38"),
    "email" : "test@test.com",
    "showMessage" : true,
    "__v" : 0
}

/* 2 */
{
    "_id" : ObjectId("5f236vgh74de563swer120rt"),
    "email" : "test1@test.com",
    "showMessage" : false,
    "__v" : 0
}

Current filtering method:

Message.aggregate([{
            $match: {
                enabled: true,
                deleted: false
            }
        }, {
            $lookup: {
                from: 'users',
                localField: 'user',
                foreignField: '_id',
                as: 'user'
            }
        }], function(err, messages) {
            if (err) {
                reject(err);
            } else {
                var filteredMessages = this.filterMessages(messages);
                //do other stuff with the filtered data
            }
        });

filterMessages(messages) {
    return messages.filter((current) => {
        return current.user[0].showMessage;
    });
}

As you can see, I am trying to get messagesusing the property showMessagesfrom user, but I execute the filter after I get all the messages first, and this is an inefficient way to do this.

Is there a way to get only the messages that I need, filtering them using a property from another collection?

: , , , , , .

+4
1

:

Message.aggregate([
  { "$match": {
    "enabled": true,
    "deleted": false  
  }},
  { "$lookup": {
    "from": "users",
    "localField": "user",
    "foreignField": "_id",
    "as": "user"
  }},
  { "$unwind": "user" },
  { "$redact": {
      "if": "$user.showMessage",
      "then": "$$KEEP",
      "else": "$$PRUNE"
  }}
],function(err,messages) {
    if (err) reject(err);
    // Already filtered
})

, $unwind ( $lookup " ", $redact , true/false.

$lookup , :

User.aggregate([
  { "$match": { "showMessage": true } },
  { "$lookup": {
    "from": "messages",
    "localField": "_id",
    "foreignField": "user",
    "as": "messages"
  }},
  { "$unwind": "$messages" },
  { "$match": {
      "messages.enabled": true,
      "messages.deleted": false
  }},
  { "$project": {
    "_id": "$messages._id",
    "user": {
      "_id": "$_id",
      "email": "$email",
      "showMessage": "$showMessage"
    },
    "text": "$messages.text",
    "deleted": "$messages.deleted",
    "enabled": "$messages.enabled"
  }}
],function(err,messages) {

})

$lookup "" - , "" "", " . .

​​ "" .


- "reverse", _id User , . , , $in :

async.waterfall
  [
    function(callback) {
      User.find({ "showMesage": true }).select("_id").exec(callback);
    },
    function(users,callback) {
      Message.find({
        "user": { "$in": users.map((current) => { return current._id }) },
        "enabled": true,
        "deleted": false
      }).populate("user").exec(callback);
    }
  ],function(err,messages) {
    // filter and populated
  }
)

$lookup, .

, , , . , "" $lookup $in . , , "" .

+1

All Articles