Skip to content

Commit c691969

Browse files
committed
Tweaking the query builder for #165
1 parent ba86fce commit c691969

File tree

2 files changed

+47
-29
lines changed

2 files changed

+47
-29
lines changed

src/Jenssegers/Mongodb/Query/Builder.php

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function __construct(Connection $connection)
6363
* @param array $columns
6464
* @return mixed
6565
*/
66-
public function find($id, $columns = array('*'))
66+
public function find($id, $columns = array())
6767
{
6868
return $this->where('_id', '=', $this->convertKey($id))->first($columns);
6969
}
@@ -74,7 +74,7 @@ public function find($id, $columns = array('*'))
7474
* @param array $columns
7575
* @return array|static[]
7676
*/
77-
public function getFresh($columns = array('*'))
77+
public function getFresh($columns = array())
7878
{
7979
$start = microtime(true);
8080

@@ -83,68 +83,69 @@ public function getFresh($columns = array('*'))
8383
// all of the columns on the table using the "wildcard" column character.
8484
if (is_null($this->columns)) $this->columns = $columns;
8585

86-
// Drop all columns if * is present, MongoDB does not work this way
86+
// Drop all columns if * is present, MongoDB does not work this way.
8787
if (in_array('*', $this->columns)) $this->columns = array();
8888

8989
// Compile wheres
9090
$wheres = $this->compileWheres();
9191

92-
// Aggregation query
92+
// Use MongoDB's aggregation framework when using grouping or aggregation functions.
9393
if ($this->groups || $this->aggregate)
9494
{
9595
$group = array();
9696

97-
// Apply grouping
97+
// Add grouping columns to the $group part of the aggregation pipeline.
9898
if ($this->groups)
9999
{
100100
foreach ($this->groups as $column)
101101
{
102-
// Mark column as grouped
103102
$group['_id'][$column] = '$' . $column;
104103

105-
// Aggregate by $last when grouping, this mimics MySQL's behaviour a bit
104+
// When grouping, also add the $last operator to each grouped field,
105+
// this mimics MySQL's behaviour a bit.
106106
$group[$column] = array('$last' => '$' . $column);
107107
}
108108
}
109109
else
110110
{
111111
// If we don't use grouping, set the _id to null to prepare the pipeline for
112-
// other aggregation functions
112+
// other aggregation functions.
113113
$group['_id'] = null;
114114
}
115115

116-
// When additional columns are requested, aggregate them by $last as well
117-
foreach ($this->columns as $column)
118-
{
119-
// Replace possible dots in subdocument queries with underscores
120-
$key = str_replace('.', '_', $column);
121-
$group[$key] = array('$last' => '$' . $column);
122-
}
123-
124-
// Apply aggregation functions, these may override previous aggregations
116+
// Add aggregation functions to the $group part of the aggregation pipeline,
117+
// these may override previous aggregations.
125118
if ($this->aggregate)
126119
{
127120
$function = $this->aggregate['function'];
128121

129122
foreach ($this->aggregate['columns'] as $column)
130123
{
131-
// Replace possible dots in subdocument queries with underscores
132-
$key = str_replace('.', '_', $column);
133-
134-
// Translate count into sum
124+
// Translate count into sum.
135125
if ($function == 'count')
136126
{
137-
$group[$key] = array('$sum' => 1);
127+
$group['aggregate'] = array('$sum' => 1);
138128
}
139-
// Pass other functions directly
129+
// Pass other functions directly.
140130
else
141131
{
142-
$group[$key] = array('$' . $function => '$' . $column);
132+
$group['aggregate'] = array('$' . $function => '$' . $column);
143133
}
144134
}
145135
}
146136

147-
// Build pipeline
137+
// If no aggregation functions are used, we add the additional select columns
138+
// to the pipeline here, aggregating them by $last.
139+
else
140+
{
141+
foreach ($this->columns as $column)
142+
{
143+
$key = str_replace('.', '_', $column);
144+
$group[$key] = array('$last' => '$' . $column);
145+
}
146+
}
147+
148+
// Build the aggregation pipeline.
148149
$pipeline = array();
149150
if ($wheres) $pipeline[] = array('$match' => $wheres);
150151
$pipeline[] = array('$group' => $group);
@@ -238,7 +239,7 @@ public function generateCacheKey()
238239
* @param array $columns
239240
* @return mixed
240241
*/
241-
public function aggregate($function, $columns = array('*'))
242+
public function aggregate($function, $columns = array())
242243
{
243244
$this->aggregate = compact('function', 'columns');
244245

@@ -251,9 +252,9 @@ public function aggregate($function, $columns = array('*'))
251252

252253
if (isset($results[0]))
253254
{
254-
// Replace possible dots in subdocument queries with underscores
255-
$key = str_replace('.', '_', $columns[0]);
256-
return $results[0][$key];
255+
$result = (array) $results[0];
256+
257+
return $result['aggregate'];
257258
}
258259
}
259260

tests/QueryTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,20 @@ public function testSelect()
7777

7878
$this->assertEquals('John Doe', $user->name);
7979
$this->assertEquals(null, $user->age);
80+
$this->assertEquals(null, $user->title);
8081

8182
$user = User::where('name', 'John Doe')->select('name', 'title')->first();
8283

8384
$this->assertEquals('John Doe', $user->name);
8485
$this->assertEquals('admin', $user->title);
8586
$this->assertEquals(null, $user->age);
8687

88+
$user = User::where('name', 'John Doe')->select(array('name', 'title'))->get()->first();
89+
90+
$this->assertEquals('John Doe', $user->name);
91+
$this->assertEquals('admin', $user->title);
92+
$this->assertEquals(null, $user->age);
93+
8794
$user = User::where('name', 'John Doe')->get(array('name'))->first();
8895

8996
$this->assertEquals('John Doe', $user->name);
@@ -185,6 +192,16 @@ public function testGroupBy()
185192
$this->assertEquals(33, $users[1]->age);
186193
}
187194

195+
public function testCount()
196+
{
197+
$count = User::where('age', '<>', 35)->count();
198+
$this->assertEquals(6, $count);
199+
200+
// Test for issue #165
201+
$count = User::select('_id', 'age', 'title')->where('age', '<>', 35)->count();
202+
$this->assertEquals(6, $count);
203+
}
204+
188205
public function testSubquery()
189206
{
190207
$users = User::where('title', 'admin')->orWhere(function($query)

0 commit comments

Comments
 (0)