1

I have a schema that has a sub array and each of its elements reference another schema like so:

{
 _id: "5fed222d806311ec81d6df23"
 someOtherNestedDoc: {
    _id: "abc",
    someOtherField: 10
 },
 matches: [
   {
      _id: "5fed222d806311ec81d6daf3",
      user: "5fed222d806311ec81d6dcf3",
      probability: 10
   },
   {
      _id: "5fed222d806311ec81d6d1f3",
      user: "5fed222d806311ec81d62cf3",
      probability: 20
   },
 ]
}

I want to do a Mongoose aggregate, in which I lookup the user reference for every match, and only project 3 fields for it, 2 are already existing, the third one is the sum of an array of that schema, so that in the end, I have something like this:

{
 _id: "5fed222d806311ec81d6df23"
 someOtherNestedDoc: {
    _id: "abc",
    someOtherField: 10
 },
 matches: [
   {
      _id: "5fed222d806311ec81d6daf3",
      user: {
         firstName: "Max",
         lastName: "Mustermann",
         totalExpenses: 100
      },
      probability: 10
   },
   {
      _id: "5fed222d806311ec81d6d1f3",
      user: {
         firstName: "Herbert",
         lastName: "Mustermann",
         totalExpenses: 200
      },,
      probability: 20
   },
 ]
}

And the users would look like this:

{
  _id: "5fed222d806311ec81d6dcf3",
  firstName: "Max",
  lastName: "Mustermann",
  password: "test",
  expenses: [
    {
      _id: 1,
     price: 50
    },
    {
      _id: 2,
     price: 50
    },
   ]
}

{
  _id: "5fed222d806311ec81d62cf3",
  firstName: "Herbert",
  lastName: "Mustermann",
  password: "test2",
  expenses: [ 
    {
      _id: 3,
     price: 75
    },
    {
      _id: 4,
     price: 125
    },
   ]
}
0

1 Answer 1

1
  • $unwind deconstruct matches array
  • $lookup with user collection and pass user id in let,
    • $match userId condition
    • $project to show required fields, get sum of expenses.price
  • $unwind deconstruct user array
  • $group by _id and reconstruct matches array
db.col1.aggregate([
  { $unwind: "$matches" },
  {
    "$lookup": {
      "from": "user",
      let: { userId: "$matches.user" },
      pipeline: [
        { $match: { $expr: { $eq: ["$_id", "$$userId"] } } },
        {
          $project: {
            _id: 0,
            firstName: 1,
            lastName: 1,
            totalExpenses: { $sum: "$expenses.price" }
          }
        }
      ],
      "as": "matches.user"
    }
  },
  { $unwind: "$matches.user" },
  {
    $group: {
      _id: "$_id",
      matches: { $push: "$matches" }
    }
  }
])

Playground

Sign up to request clarification or add additional context in comments.

2 Comments

that generally works well, the only thing is that, if I have other fields besides "matches" in the original document, then these fields are lost. How can I preserve those? I edited the question.
you can use $first operator with field name look at this playground

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.