1

Let us say I have a collection of users. Each user has assets. There are some statistical measures that I want to perform on assets. But in order to be able to do this I need to only have the assets in the projection as an input for the aggregate. How could this be achieved?

I want to be able to do a bunch of aggregate operations on assets. These operations would include filtering, limit and skip so I would be using operators like $skip, $match, $limit, and others. But in order for me to perform these operations on the embedded array, I would need an operator that takes a user document and outputs the assets array embedded into it.

Simply I want an operator that that takes a user document with the following schema and outputs an array of assets that I further perform aggregate operations on it.

user:{
   name: string,
   assets: Asset[],
   age: number
}

I tried this aggregate operations but it is not working as I expected.

db.getCollection('users').aggregate( [ 
{ $match: {_id: ObjectId("5ae837dca9a8e04dd0689824")} } ,
{ $project : { assets: 1  } },
] )

It outputs an array that have one user document in which the assets are embedded inside like this

[{
"_id" : ObjectId("5ae837dca9a8e04dd0689824"),
"assets" : [{_id:ObjectId("1"), assetName: 'tt' }, {_id : ObjectId("2"), assetName: 'rr'}]
}] 

I need to have the output like the one below

[
{_id:ObjectId("1"), assetName: 'tt'}, 
{_id:ObjectId("2"), assetName: 'rr'}
]
4
  • Please show your sample documents and expected output Commented May 1, 2018 at 21:13
  • Done. I added an explanation Commented May 1, 2018 at 21:18
  • It's not really enough of an explanation. Better to show a few sample documents and the result you expect to achieve. Ideally we really want you to "show your attempt" as well, since we're happy to help you with your code but less happy to do your job for "free" as it were. See How do I ask a good question? and it's various linked topics including How to create a Minimal, Complete, and Verifiable example Commented May 2, 2018 at 3:21
  • I updated my question again. Commented May 2, 2018 at 4:41

1 Answer 1

1

Two steps to do that (plus $match):

  • $unwind to transform an array of subdocuments to multiple documents having one subdocument
  • $replaceRoot to promote subdocument to a new root

Try:

db.users.aggregate([
    { $match: {_id: ObjectId("5ae837dca9a8e04dd0689824")} },
    { $unwind: "$assets" },
    { $replaceRoot: { newRoot: "$assets" } }
])
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for this answer and thumbs up, but don't you think there is a more performant solution.
@YoussefSherif nothing comes to my mind since I believe there are no replacements for those two operators. What do you mean by performant ? If you start with $match and perform $unwind on single document then your result set shouldn't be so huge I guesa

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.