2

I have the following data structure in MongoDB:

{ "_id" : ObjectId( "xy" ),
  "litter" : [ 
    { "puppy_name" : "Tom",
      "birth_timestamp" : 1353963728 }, 
    { "puppy_name" : "Ann",
      "birth_timestamp" : 1353963997 }
   ]
}

I have many of these "litter" documents with varying number of puppies. The highter the timestamp number, the younger the puppy is (=born later).

What I would like to do is to retrieve the five youngest puppies from the collection accross all litter documents.

I tried something along

find().sort('litter.birth_timestamp' : -1).limit(5)

to get the the five litters which have the youngest puppies and then to extract the youngest puppy from each litter in the PHP script.

But I am not sure if this will work properly. Any idea on how to do this right (without changing the data structure)?

Goeran
  • 362
  • 1
  • 2
  • 8

1 Answers1

1

You can use the new Aggregation Framework in MongoDB 2.2 to achieve this:

<?php
    $m = new Mongo();
    $collection = $m->selectDB("test")->selectCollection("puppies");

    $pipeline = array(

        // Create a document stream (one per puppy)
        array('$unwind' => '$litter'),

        // Sort by birthdate descending
        array('$sort' => array (
            'litter.birth_timestamp' => -1
        )),

        // Limit to 5 results
        array('$limit' => 5)
    );

    $results = $collection->aggregate($pipeline);
    var_dump($results);
?>
Stennie
  • 63,885
  • 14
  • 149
  • 175
  • Note: The `aggregate()` helper was added in the PHP 1.3.0 driver release. You can still do aggregations with older versions of the driver by passing the pipeline [using a `command()`](http://stackoverflow.com/questions/11290809). – Stennie Nov 30 '12 at 20:25
  • 1
    Great - thank you very much for you wonderfully detailed answer! – Goeran Nov 30 '12 at 21:30