Faceted MongoDB search in PHP.

The Problem: Aggregating counts of data based on date facets.

Dependencies: Shanty Mongo, MongoDB Native Driver

The snippet:

$result = facetSearch(strtotime("13 Mar"), strtotime("23 Mar"), 10, "d M");
 
function facetSearch($start_timestamp, $end_timestamp, $periods, $dateFormat)
{
  $diff = $end_timestamp - $start_timestamp;
  $period = $diff / $periods;
  $mapFunction = new MongoCode("function() {
    var tstamp = this.created_at.getTime() / 1000;
    var period = Math.floor((tstamp - $start_timestamp) / $period);
    emit(period.toString(), 1);
  }");
  $reduceFunction = new MongoCode("function(k,v) {
    var sum=0;
    for(var i in v) sum += v[i];
    return sum;
  }");
  $return = Model_Mongo_Activities::getMongoDb()->command(array(
      "mapreduce" => "users",
      "map" => $mapFunction,
      "reduce" => $reduceFunction,
      "out" => array("inline" => true)));
 
  if (isset($return['results']))
  {
    $numericPeriods = array();
    foreach ($return['results'] as $result)
    {
      $numericPeriods[$result['_id']] = $result['value'];
    }
 
    $datePeriods = array();
    for ($i = 0; $i < $periods; $i++)
    {
      $timestamp = $i * $period + $start_timestamp;
      $formattedDate = date($dateFormat, $timestamp);
      if (isset($numericPeriods[$i]))
      {
        $datePeriods[$formattedDate] = $numericPeriods[$i];
      }
      else
      {
        $datePeriods[$formattedDate] = 0;
      }
    }
 
    return $datePeriods;
  }
  else
  {
    return false;
  }
}

The result of the above will look something like this:

array(4) {
  ["13 Mar"] => float(2)
  ["14 Mar"] => float(3)
  ["15 Mar"] => float(2)
  ["16 Mar"] => float(0)
  ["17 Mar"] => float(0)
  ["18 Mar"] => float(0)
  ["19 Mar"] => float(0)
  ["20 Mar"] => float(0)
  ["21 Mar"] => float(0)
  ["22 Mar"] => float(2)
}

Combine the results with Google Line Charts and you can quickly and easily get a nice graph back: