Home > Software engineering >  How to filter MongoDB documents based on one specific document's array?
How to filter MongoDB documents based on one specific document's array?

Time:05-19

I have a collection like this:

{
  _id: "blabla",
  userName: "blablabla",
  ..
  interactedUsers: [
    "blabla2"
    "some other user's id",
    "some other user's id",
  ]
},
{
  _id: "blabla2",
  userName: "blablabla2",
  ..
  interactedUsers: [
    "some other user's id",
    "some other user's id",
  ]
},

Now if i am the user with "_id: "blabla" i want to fetch all users except "blabla2" because its in my "interactedUsers" array. How can i do that? I tried so many aggregation combinations but couldn't really get the wanted result.

CodePudding user response:

Since you probably don't want to use $facet as it will merge all your collection into one big document, another option is to use $lookup.

This allows you to add the "ignored" document to all other documents and then remove from the answer the ones that contain it. The advantage here is that all your documents are kept separated along the process:

db.collection.aggregate([
  {
    $addFields: {"ignore": "blabla" }
  },
  {
    $lookup: {
      from: "collection",
      localField: "ignore",
      foreignField: "_id",
      as: "ignore"
    }
  },
  {
    $set: {ignore: {$arrayElemAt: ["$ignore", 0]}}
  },
  {
    $match: {
      $expr: {$not: {$in: ["$_id", "$ignore.interactedUsers"]}}
    }
  },
  {
    $unset: "ignore"
  },
  {
    $match: {$expr: {$ne: ["$_id", "blabla"]}}
  }
])

Playground example

CodePudding user response:

Here's another way to return all "_id" in the collection not in "interactedUsers".

db.collection.aggregate([
  { "$match": { "_id": "blabla0" } },
  {
    "$lookup": {
      "from": "collection",
      "let": { "notIds": { "$setUnion": [ [ "$_id" ], "$interactedUsers" ] } },
      "pipeline": [
        { "$match": { "$expr": { "$not": { "$in": [ "$_id", "$$notIds" ] } } } },
        { "$project": { "_id": 1 } }
      ],
      "as": "strangers"
    }
  },
  {
    "$set": {
      "strangers": {
        "$map": {
          "input": "$strangers",
          "in": "$$this._id"
        }
      }
    }
  }
])

Try it on mongoplayground.net.

  • Related