2

I'm trying to solve a problem for some time now but with no luck, unfortunately. So I'm refactoring some old code (which used the all known get each doc query and for loop over it) and I'm trying to aggregate the results to remove the thousands of calls the BE is making.

The current doc looks like this

{
    "_id" : ObjectId("5c176fc65f543200019f8d66"),
    "category" : "New client",
    "description" : "",
    "createdById" : ObjectId("5c0a858da9c0f000018382bb"),
    "createdAt" : ISODate("2018-12-17T09:43:34.642Z"),
    "sentAt" : ISODate("2018-12-17T09:44:25.902Z"),
    "scheduleToBeSentAt" : ISODate("2018-01-17T11:43:00.000Z"),
    "recipients" : [ 
        {
            "user" : ObjectId("5c0a858da9c0f000018382b5"),
            "status" : {
                "approved" : true,
                "lastUpdated" : ISODate("2018-01-17T11:43:00.000Z")
            }
        }, 
        {
            "user" : ObjectId("5c0a858da9c0f000018382b6"),
            "status" : {
                "approved" : true,
                "lastUpdated" : ISODate("2018-01-17T11:43:00.000Z")
            }
        }, 
    ],
    "recipientsGroup" : "All",
    "isActive" : false,
    "notificationSent" : true
}

The field recipients.user is an objectID of a user from the Users collection. What is the correct way to modify this so the result will be

{
    "_id": ObjectId("5c176fc65f543200019f8d66"),
    "category": "New client",
    "description": "",
    "createdById": ObjectId("5c0a858da9c0f000018382bb"),
    "createdAt": ISODate("2018-12-17T09:43:34.642Z"),
    "sentAt": ISODate("2018-12-17T09:44:25.902Z"),
    "scheduleToBeSentAt": ISODate("2018-01-17T11:43:00.000Z"),
    "recipients": [{
            "user": {
                "_id": ObjectId("5c0a858da9c0f000018382b5"),
                "title": "",
                "firstName": "Monique",
                "lastName": "Heinrich",
                "qualification": "Management",
                "isActive": true
            },
            "status": {
                "approved": true,
                "lastUpdated": ISODate("2018-01-17T11:43:00.000Z")
            }
        },
        {
            "user": {
                "_id": ObjectId("5c0a858da9c0f000018382b6"),
                "title": "",
                "firstName": "Marek",
                "lastName": "Pucelik",
                "qualification": "Management",
                "isActive": true
            },
            "status": {
                "approved": true,
                "lastUpdated": ISODate("2018-01-17T11:43:00.000Z")
            }
        },
    ],
    "recipientsGroup": "All",
    "isActive": false,
    "notificationSent": true
}

An aggregation is a powerful tool but sometimes the simple solution makes your brain hurt.....

I tried something like this but with no luck also.

db.getCollection('Protocols').aggregate([
{
    $lookup: {
        from: "Users",
        localField: "recipients.user",
        foreignField: "_id",
        as: "users"
    }
},
{
    $project: {
        "recipients": {
            "status": 1,
            "user": {
                $filter: {
                input: "$users",
                cond: { $eq: ["$$this._id", "$user"] }
                }
            },
        }
    }
}
])
halfer
  • 19,824
  • 17
  • 99
  • 186
GrimR1P
  • 152
  • 1
  • 12
  • https://stackoverflow.com/questions/46323106/mongodb-find-and-findone-with-nested-array-filtering/46323107#46323107 if I understand your question correctly – Vaiden Feb 20 '19 at 13:28
  • In this example, the result is being filtered from the original DOC. I need to replace a field in the array of objects of my result with a value from filtered aggregation array result – GrimR1P Feb 21 '19 at 07:44
  • This is exactly what I did there. The filtered results override the original values.You can have a broader explanation here: https://www.devsbedevin.net/mongodb-find-findone-with-nested-array-filtering-finally/ – Vaiden Sep 07 '19 at 09:45

1 Answers1

0

You can use the $lookup operator in your aggregation pipeline

https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/

But for performance reason you'd rather duplicate user object in your recipents array to avoid such complex queries.

Pierre Clocher
  • 1,067
  • 1
  • 9
  • 21