how to use $group in mongodb/mongoose aggregation in grouping the subdocuments? <p>This corresponds to my question on <a href="http://stackoverflow.com/questions/20919149/how-to-use-mapreduce-in-mongoose-mongodb-query-subdocument">how to use mapreduce in mongoose/mongodb query subdocument?</a>, in that question, I used the map reduce to query the subdocument.</p> <p>Now I tried the solution of aggregation to query all the messages sent from 'user1'</p> <pre><code>model.aggregate( { $match: {user:'username'} }, // query the document { $unwind: "$msgs" }, // break the 'msgs' array into subdocuments { $match: { "msgs.s" : 'user1'} }, // match the filed in subdocuments { $project: { _id: 0, 'msgs.d':1,'msgs.m':1,'msgs.r':1 }}, // project the fileds { $group : { _id : "$_id", msgs : { $addToSet : "$msgs" } }}, // don't know how to group the data { $sort: {"msgs.d " : -1} }, function (err, data ) { if(err) callback(err); else callback(null,data); }) </code></pre> <p>the results I got is </p> <pre><code>[ { msgs: { m: 'I want to meet you', d: Sat Jan 04 2014 08:52:54 GMT+0000 (GMT), r: false } }, { msgs: { m: 'I want to meet you', d: Sat Jan 04 2014 08:53:02 GMT+0000 (GMT), r: false } }, { msgs: { m: 'I want to meet youd', d: Sat Jan 04 2014 08:53:06 GMT+0000 (GMT), r: false } }, ] </code></pre> <p>it is right results, but still not in good format, I think I don't know how to use the $group to group the subdocument into a flatten array.</p> <p>The result I want is </p> <pre><code>{'msgs':[ { m: 'I want to meet you', d: Sat Jan 04 2014 08:52:54 GMT+0000 (GMT), r: false }, { m: 'I want to meet you', d: Sat Jan 04 2014 08:53:02 GMT+0000 (GMT), r: false }, { m: 'I want to meet youd', d: Sat Jan 04 2014 08:53:06 GMT+0000 (GMT), r: false }, ]} </code></pre> <p>how to use the $group in aggregation?</p> <p>if I uncomment the $group in the query.</p> <p>the result I got is like the following</p> <pre><code>[ { _id: null, msgs:[ [Object], [Object], [Object], [Object], [Object] ] } ] </code></pre> <p>Thanks for JohnnyHK 's answer, it helps me a lot in understanding the aggregate. Now I have two more little problems</p> <p><strong>1.</strong> the subdocuments I fetched is not sorted according to the time, in my code, I used <code>{ $sort: {"msgs.d " : -1} }</code> in the query to sort all the subdocuments , but failed to work</p> <p><strong>2.</strong> If I need to add a 'sender' field in the results accompanied with all his sent messages, how can I do it in the $group I tried this way </p> <pre><code>{ $group : { sender : "$msgs.s", msgs : { $addToSet : "$msgs" } }} </code></pre> <p>or</p> <pre><code>{ $group : { sender : sender, msgs : { $addToSet : "$msgs" } }} </code></pre> <p>doesn't work</p> <p><strong>3.</strong> the current result gives me two levels of array, can I remove the first outer array, since it is not needed</p>