1

I have a user schema that contains a value called amputationInfo:

amputationInfo: [
      {
        type: String,
      },
    ],

Here is an example of what that might look like in the database:

amputationInfo: [
 "Double Symes/Boyd", 
  "Single Above-Elbow"
]

I have a review Schema that allows a user to leave a review, it contains a reference to the user who left it:

user: {
  type: mongoose.Schema.ObjectId,
  ref: 'User',
  require: [true, 'Each review must have an associated user!'],
},

When a user leaves a review, I want to create an aggregate function that looks up the user on the review, finds their amputationInfo, loops through the array and adds up the total amount of users that contain "Double Symes/Boyd", "Single Above-Elbow"

So if we have 3 users and their amputationInfo is as follows:

 amputationInfo: [
  "Double Symes/Boyd", 
  "Single Above-Elbow"
 ]

amputationInfo: [ 
  "Single Above-Elbow"
]

amputationInfo: []

The return from the aggregate function will count each term and add one to the corresponding value and look something like this:

[
 {
    doubleSymesBoyd: 1,
    singleAboveElbow: 2
  }
]

Here is what I have tried, but I just don't know enough about mongoDB to solve the issue:

[
  {
    '$match': {
      'prosthetistID': new ObjectId('6126ca6148f34c00189f86f5')
    }
  }, {
    '$lookup': {
      'from': 'users', 
      'localField': 'user', 
      'foreignField': '_id', 
      'as': 'userInfo'
    }
  }, {
    '$unwind': {
      'path': '$userInfo'
    }
  }
]

After the $unwind, the resulting object has a userInfo key, that contains an amputationInfo array nested:

Explainer picture

1 Answer 1

1

You can have following stages

  • $unwind to deconstruct the array
  • first $group to get the sum of each category
  • second $group to push into one document and make it as key value pair
  • $arrayToObject to get the desired output
  • $replaceRoot to make the data output into root

Here is the code

db.collection.aggregate([
  { "$unwind": "$userInfo.amputationInfo" },
  {
    "$group": {
      "_id": "$userInfo.amputationInfo",
      "count": { "$sum": 1 }
    }
  },
  {
    $group: {
      _id: null,
      data: { $push: {
          k: "$_id",
          v: "$count"
        }
      }
    }
  },
  { $project: { data: { "$arrayToObject": "$data" } } },
  { "$replaceRoot": { "newRoot": "$data" } }
])

Working Mongo playground

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

2 Comments

Ok that is exactly as I was looking for. To take this further...what if I wanted the output to be an array like [{Single Above-Elbow: 2, Double Symes/Boyd: 2}] to sort by the largest value?
@klaurtar1 But these are key value pair where keys are unique. So I dont think (Im not sure) there is a method to sort inside object, but you can sort inside array like mongoplayground.net/p/gIrVtfQmHAC

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.