Commit 4089d6e9 authored by Jens Segers's avatar Jens Segers

Adding aggregation

parent 17234dac
...@@ -89,16 +89,15 @@ Examples ...@@ -89,16 +89,15 @@ Examples
}) })
->get(); ->get();
**Distinct**
Distinct is limited to a single column.
$names = Users::distinct('name')->get();
**Group By** **Group By**
Grouping does not support sorting and limiting at this moment. $users = Users::groupBy('title')->get(array('title', 'name'));
**Aggregation**
$users = Users::groupBy('title')->get(); $price = DB::table('orders')->max('price');
$price = DB::table('orders')->min('price');
$price = DB::table('orders')->avg('price');
$total = DB::table('users')->sum('votes');
All basis insert, update, delete and select methods should be implemented. Feel free to fork and help completing this library! All basis insert, update, delete and select methods should be implemented. Feel free to fork and help completing this library!
\ No newline at end of file
...@@ -23,9 +23,6 @@ class Query extends \Illuminate\Database\Query\Builder { ...@@ -23,9 +23,6 @@ class Query extends \Illuminate\Database\Query\Builder {
'<=' => '$lte', '<=' => '$lte',
'>' => '$gt', '>' => '$gt',
'>=' => '$gte', '>=' => '$gte',
'in' => '$in',
'exists' => '$exists',
'or' => '$or',
); );
/** /**
...@@ -73,62 +70,78 @@ class Query extends \Illuminate\Database\Query\Builder { ...@@ -73,62 +70,78 @@ class Query extends \Illuminate\Database\Query\Builder {
$this->columns = array(); $this->columns = array();
} }
// Compile wheres
$wheres = $this->compileWheres();
if ($this->distinct) // Use aggregation framework if needed
if ($this->groups || $this->aggregate)
{ {
// We can only return an array of distinct values for a single column $pipeline = array();
return $this->collection->distinct($this->distinct, $this->compileWheres());
}
else if(count($this->groups))
{
// We can pass our wheres as a condition
$options = array();
$options['condition'] = $this->compileWheres();
// Initial value and reduce code // Group
$initial = array("item" => ""); $group = array();
$reduce = "function (obj, prev) { prev.item = obj; }"; $group['_id'] = $this->groups ? $this->groups : 0;
// Get results // Columns
$result = $this->collection->group($this->groups, $initial, $reduce, $options); foreach ($this->columns as $column)
$items = $result['retval']; {
$group[$column] = array('$last' => '$' . $column);
}
// Transform results to a nice array // Apply aggregation functions
$results = array(); if ($this->aggregate)
foreach($items as $item) {
foreach ($this->aggregate['columns'] as $column)
{ {
$results[] = $item['item']; $group[$column] = array('$' . $this->aggregate['function'] => '$' . $column);
} }
}
if ($wheres) $pipeline[] = array('$match' => $match);
$pipeline[] = array('$group' => $group);
// Apply order and limit
if ($this->orders) $pipeline[] = array('$sort' => $this->orders);
if ($this->limit) $pipeline[] = array('$limit' => $this->limit);
// Return these results since we don't have a MongoCursor $results = $this->collection->aggregate($pipeline);
return $results;
// Return results
return $results['result'];
} }
else else
{ {
// Get the MongoCursor // Get the MongoCursor
$cursor = $this->collection->find($this->compileWheres(), $this->columns); $cursor = $this->collection->find($wheres, $this->columns);
}
// Apply order // Apply order, offset and limit
if ($this->orders) if ($this->orders) $cursor->sort($this->orders);
{ if ($this->offset) $cursor->skip($this->offset);
$cursor->sort($this->orders); if ($this->limit) $cursor->limit($this->limit);
// Return results
return $cursor;
}
} }
// Apply offset /**
if ($this->offset) * Execute an aggregate function on the database.
*
* @param string $function
* @param array $columns
* @return mixed
*/
public function aggregate($function, $columns = array('*'))
{ {
$cursor->skip($this->offset); $this->aggregate = compact('function', 'columns');
}
// Apply limit $results = $this->get($columns);
if ($this->limit)
if (isset($results[0]))
{ {
$cursor->limit($this->limit); return $results[0][$columns[0]];
} }
// Return results
return $cursor;
} }
/** /**
...@@ -157,7 +170,7 @@ class Query extends \Illuminate\Database\Query\Builder { ...@@ -157,7 +170,7 @@ class Query extends \Illuminate\Database\Query\Builder {
foreach ($groups as $group) foreach ($groups as $group)
{ {
$this->groups[$group] = 1; $this->groups[$group] = '$' . $group;
} }
return $this; return $this;
...@@ -246,18 +259,6 @@ class Query extends \Illuminate\Database\Query\Builder { ...@@ -246,18 +259,6 @@ class Query extends \Illuminate\Database\Query\Builder {
return $this; return $this;
} }
/**
* Force the query to only return distinct results.
*
* @return Builder
*/
public function distinct($column = false)
{
$this->distinct = $column;
return $this;
}
/** /**
* Compile the where array * Compile the where array
* *
...@@ -310,7 +311,7 @@ class Query extends \Illuminate\Database\Query\Builder { ...@@ -310,7 +311,7 @@ class Query extends \Illuminate\Database\Query\Builder {
if ($boolean == 'or') if ($boolean == 'or')
{ {
return array($this->conversion[$boolean] => array($query)); return array('$or' => array($query));
} }
return $query; return $query;
...@@ -325,7 +326,7 @@ class Query extends \Illuminate\Database\Query\Builder { ...@@ -325,7 +326,7 @@ class Query extends \Illuminate\Database\Query\Builder {
if ($boolean == 'or') if ($boolean == 'or')
{ {
return array($this->conversion[$boolean] => array($compiled)); return array('$or' => array($compiled));
} }
return $compiled; return $compiled;
...@@ -335,7 +336,7 @@ class Query extends \Illuminate\Database\Query\Builder { ...@@ -335,7 +336,7 @@ class Query extends \Illuminate\Database\Query\Builder {
{ {
extract($where); extract($where);
return array($column => array($this->conversion['in'] => $values)); return array($column => array('$in' => $values));
} }
public function compileWhereNull($where) public function compileWhereNull($where)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment