Search code examples
databasemongodbmongooseaggregatenosql-aggregation

Aggregation to filter reference in MongoDB


I'm trying to make an aggregate work with mongoose but I'm having a problem, I'm getting this result:

[
   {
     _id: new ObjectId("630bb658370cc689973c5bb4"),
     isRead: true,
     user: new ObjectId("630273bbe0f3f82d85b149bd"),
     globalRef: new ObjectId("630bb649370cc689973c5b62"),
   },
   {
     _id: new ObjectId("630bb649370cc689973c5b62"),
     isRead: false,
   },
   {
     _id: new ObjectId("6306bcf16fa60080148fefb6"),
     isRead: false,
   },
   {
     _id: new ObjectId("630273bbe0f3f82d85b149bd"),
     isRead: false,
     user: new ObjectId("630273bbe0f3f82d85b149bd")
   },
   {
     _id: new ObjectId("6306bcf16fa60080148fefb7"),
     isRead: true,
     user: new ObjectId("630273bbe0f3f82d85b149bd")
   }
]

We can see that the first element has a reference (globalRef) to the second,

I would like to remove elements if another one exists with the latter as a reference, is this possible with $match? $group? $project? $filter?

Desired result:

[
   {
     _id: new ObjectId("630bb658370cc689973c5bb4"),
     isRead: true,
     user: new ObjectId("630273bbe0f3f82d85b149bd"),
     globalRef: new ObjectId("630bb649370cc689973c5b62"),
   },
   {
     _id: new ObjectId("6306bcf16fa60080148fefb6"),
     isRead: false,
   },
   {
     _id: new ObjectId("630273bbe0f3f82d85b149bd"),
     isRead: false,
     user: new ObjectId("630273bbe0f3f82d85b149bd")
   },
   {
     _id: new ObjectId("6306bcf16fa60080148fefb7"),
     isRead: true,
     user: new ObjectId("630273bbe0f3f82d85b149bd")
   }
]

Thanks for your help


Solution

  • Query

    • you can do a self-lookup _id with globalRef (make index on globalRef to be fast)
    • after join, keep document if results is empty(no match found)
    • unset to remove the results field

    Playmongo

    coll.aggregate(
    [{"$lookup": 
       {"from": "coll",
        "localField": "_id",
        "foreignField": "globalRef",
        "as": "results"}},
     {"$match": {"$expr": {"$eq": ["$results", []]}}},
     {"$unset": ["results"]}])