title: MongoDb: How to aggregate, group and sort on date field?
body: <p>In my MongoDB people collection I need to filter people with the same 'alias' property value, keeping the first one of them, and also keeping all people with a null 'alias'.</p>
  
  <p>Data is like this:</p>
  
  <pre><code>{ "_id" : "1", "flag" : true,  "name" : "Alice",    "alias" : null, "dateOfBirth": new ISODate('1995-12-27T00:00:00.000Z') },
  { "_id" : "2", "flag" : true,  "name" : "Bob",      "alias" : "4c", "dateOfBirth": new ISODate('1996-12-27T00:00:00.000Z') },
  { "_id" : "3", "flag" : true,  "name" : "Bobby",    "alias" : "4c", "dateOfBirth": new ISODate('1997-12-27T00:00:00.000Z') },
  { "_id" : "4", "flag" : true,  "name" : "Cristina", "alias" : null, "dateOfBirth": new ISODate('1998-12-27T00:00:00.000Z') },
  { "_id" : "5", "flag" : false, "name" : "Diego",    "alias" : null, "dateOfBirth": new ISODate('1999-12-27T00:00:00.000Z') },
  { "_id" : "6", "flag" : true,  "name" : "Zoe",      "alias" : "22", "dateOfBirth": new ISODate('2000-12-27T00:00:00.000Z') }
  </code></pre>
  
  <p>This is my query:</p>
  
  
  
  <pre class="lang-js prettyprint-override"><code>db.people.aggregate([ 
      { '$match': { 'flag': true } }, 
      { '$project': {
          'name': 1,          
          'alias': { 
              '$cond': [
                  { '$eq': [ '$alias', null ] }, 
                  '$_id', 
                  '$alias' 
              ]
          }
      }},
      { '$group': {
          '_id': '$alias',         
          'name':  { '$first': '$name' },          
          'id': { '$first': '$_id' }       
      }}, 
      { '$project': {
          'alias': {
              '$cond': [ 
                  { '$eq': [ '$id', '$_id' ] }, 
                  null, 
                 '$_id' 
              ]
          }, 
          'name': 1,
          '_id': '$id'
      }}
  ])
  </code></pre>
  
  <p>Which returns:</p>
  
  <pre class="lang-js prettyprint-override"><code>{ "_id" : "6", "name" : "Zoe",      "alias" : "22" }
  { "_id" : "4", "name" : "Cristina", "alias" : null }
  { "_id" : "2", "name" : "Bob",      "alias" : "4c" }
  { "_id" : "1", "name" : "Alice",    "alias" : null }
  </code></pre>
  
  <p>So far so good.</p>
  
  <p><strong>UPDATE:</strong> Up to this point the qestion is similar to <a href="https://stackoverflow.com/questions/34375163">suggested duplicate question</a>. Now comes the different part:</p>
  
  <p>I need to sort it according to "dateOfBirth" field.<br>
  Very confident, I changed the query to:</p>
  
  
  
  <pre class="lang-js prettyprint-override"><code>db.people.aggregate([ 
      { '$match': { 'flag': true } }, 
      { '$project': {
          'name': 1,          
          'dateOfBirth': 1,
          'alias': { 
              '$cond': [
                  { '$eq': [ '$alias', null ] }, 
                  '$_id', 
                  '$alias' 
              ]
          }
      }},
      { '$group': {
          '_id': '$alias',         
          'name':  { '$first': '$name' },          
          'dateOfBirth': { '$first': '$dateOfBirth' },
          'id': { '$first': '$_id' }       
      }}, 
      { '$project': {
          'alias': {
              '$cond': [ 
                  { '$eq': [ '$id', '$_id' ] }, 
                  null, 
                 '$_id' 
              ]
          }, 
          'name': 1,
          '_id': '$id',
          'dateOfBirth': 1,
      }},
      { '$sort': { 'dateOfBirth': 1 }}
  ])
  </code></pre>
  
  <p>But this gives:</p>
  
  <pre class="lang-js prettyprint-override"><code>{ "_id" : "1", "name" : "Alice",    "dateOfBirth" : ISODate("1995-12-27T00:00:00Z"), "alias" : null }
  { "_id" : "6", "name" : "Zoe",      "dateOfBirth" : null, "alias" : "22" }
  { "_id" : "4", "name" : "Cristina", "dateOfBirth" : null, "alias" : null }
  { "_id" : "2", "name" : "Bob",      "dateOfBirth" : null, "alias" : "4c" }
  </code></pre>
  
  <p>Which is wrong, of course: <code>dateOfBirth</code> field does not pass the <code>$group</code> stage...</p>
  
  <p>Any clue on how to let it pass through?</p>