basedmann
basedmann

Reputation: 3

How to filter MongoDB documents based on one specific document's array?

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.

Upvotes: 0

Views: 42

Answers (2)

rickhg12hs
rickhg12hs

Reputation: 11902

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.

Upvotes: 0

nimrod serok
nimrod serok

Reputation: 16033

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

Upvotes: 1

Related Questions