title: how to use mapreduce in mongoose/mongodb query subdocument?
body: <p>I implemented a simple message system in mongoose/mongodb, the schema is like the following </p>
  
  <pre><code>var schema = new mongoose.Schema({
      user: {type:String, required:true},
      updated: {type:Date, default:new Date()},       
      msgs: [ {m:String, // message itself 
               d:Date,   // date of message
               s: String,  // message sender
               r:Boolean   // read or not
              } ],
  });
  </code></pre>
  
  <p>all the messages are stored in msg nested array, now I want to query the messages from certain sender, for example,</p>
  
  <pre><code>{
    "_id" : ObjectId("52c7cbe6d72ecb07f9bbc148"),
    'user':'abc'
    "msgs" : [{
        "m" : "I want to meet you",
        "d" : new Date("4/1/2014 08:52:54"),
        "s" : "user1",
        "r" : false,
        "_id" : ObjectId("52c7cbe69d09f89025000005")
      }, {
        "m" : "I want to meet you",
        "d" : new Date("4/1/2014 08:52:56"),
        "s" : "user1",
        "r" : false,
        "_id" : ObjectId("52c7cbe89d09f89025000006")
      }, {
        "m" : "I want to meet you",
        "d" : new Date("4/1/2014 08:52:58"),
        "s" : "user2",
        "r" : false,
        "_id" : ObjectId("52c7cbea9d09f89025000007")
      }
     }
  </code></pre>
  
  <p>Here I have a document for user 'aa' who has three messages, two messages are from 'user1' and one message is from 'user2'. And I want to query for the messages from 'user1'</p>
  
  <p>Basically there are two ways to do it, map-reduce or aggregate.
  I tried the map-reduce solution.</p>
  
  <pre><code>var o = {}; 
  o.map = function() { 
      this.msgs.forEach(function(msg){ 
          if(msg.s == person){  emit( msg.s, {m:msg.m,d:msg.d,r:msg.r}); }
      })
  }       
  o.reduce = function(key, values) {
      var msgs = [];
      for(var i=0;i&lt;values.length;i++)
      msgs.push(values[i]);       
      return JSON.stringify(msgs);
  }
  o.query  = {user:'username'};  
  o.scope = {person:'user1'};
  model.mapReduce(o,function (err, data, stats) { 
      console.log('map reduce took %d ms', stats.processtime)
      if(err) callback(err);
      else callback(null,data);
  })
  </code></pre>
  
  <p>Ultimately, it works with results like</p>
  
  <pre><code> [ 
      { _id: 'helxsz',
      value: '[
          {"m":"I want to meet you","d":"2014-01-04T08:52:54.112Z","r":false}, ....
          ]
   ]
  </code></pre>
  
  <p>The result is what I want, but the format is a bit complex.
  How can I change to make output the format like this</p>
  
  <pre><code>    { sender: 'helxsz',
        messages: '[
          {"m":"I want to meet you","d":"2014-01-04T08:52:54.112Z","r":false}, ...
          ]
      }
  </code></pre>
  
  <p>and how I sort and limit the results, so I have to manually do it the reduce function?</p>
  
  <p>and one last the map reduce methods takes 28 ms to query the result, for the simulation, my collection has three documents, each document has a msg array of 4 subdocument. for me , 28 ms is a bit of too much for the query, is it , now I also indexed on the 'user' field.</p>