问题
Please consider the collection bellow
$people->insert(array("user_id" => "1", "day" => "Monday", 'age' => 18));
$people->insert(array("user_id" => "3", "day" => "Monday", 'age' => 24));
$people->insert(array("user_id" => "1", "day" => "Monday", 'age' => 18));
$people->insert(array("user_id" => "1", "day" => "Monday", 'age' => 18));
$people->insert(array("user_id" => "2", "day" => "Monday", 'age' => 25));
$people->insert(array("user_id" => "4", "day" => "Monday", 'age' => 33));
$people->insert(array("user_id" => "1", "day" => "Tuesday", 'age' => 18));
$people->insert(array("user_id" => "2", "day" => "Tuesday", 'age' => 25));
$people->insert(array("user_id" => "1", "day" => "Wednesday", 'age' => 18));
$people->insert(array("user_id" => "2", "day" => "Thursday", 'age' => 25));
$people->insert(array("user_id" => "1", "day" => "Friday", 'age' => 18));
Can anyone help me to get count of distinct users within a age group? For example for the schema above i would like to get
Age 0-17 = 0, Age 18-25 = 3, Age 26-32 = 0 Age > 32 = 1
I have tried to use the $cond operator but didn't manage to get it it work. Every time i try to run or change it i get one of the 2 errors:
- The "$cond" operator requires 3 operands or
- A pipeline stage specification object must contain exactly one field.
My query is bellow any help is much appreciated. Thanks in advance,
$query =
array(
$project' => array(
ageGroup' => array(
array('$cond'=> array('$user_data.age' => array('$lt' => 18),
"age_0_17",
array('$cond'=> array('$user_data.age' => array('$lte' => 25),
"age_18_25",
array('$cond'=> array('$user_data.age' => array('$lte' => 32),
"age_26_32",
"age_Above_32")))))
)
),
),
array(
'$group' => array(
'_id' => '$ageGroup',
'count' => array('$sum' => 1),
)
));
The Answer by @Neil Lunn is 90% right, it did not give me the desired output but leaded took me there.
With Neil's query the output i get is:
age_Above_32 = 1 and age_18_25 = 10
The output for distinct user_id count should be
age_Above_32 = 1 and age_18_25 = 3
To obtain that i just had to tweak Neil's query a little bit. The final query is below.
$query2 = array(
array(
'$group' => array(
'_id' => array(
'ageGroup' => array(
'$cond' => array(
array('$lt' => array( '$age', 18 )),
'age_0_17',
array(
'$cond' => array(
array( '$lte' => array( '$age', 25 )),
'age_18_25',
array(
'$cond' => array(
array( '$lte' => array ( '$age', 32 )),
'age_26_32',
'age_Above_32'
)
)
)
)
)
),
'user_id' =>'$user_id'
)
)
),
array(
'$group' => array(
'_id' => '$_id.ageGroup',
'count' => array('$sum' => 1)
))
);
回答1:
You were in the right place, but as $cond requires three arguments (being the evaluation , true result and false result) you need to "nest" these operations, which each subsequent $cond
as the false
condition. So your syntax here is a little off.
You can also do this just in the $group to avoid passing through the whole collection with a separate $project. Based on the document structure you give as an example you would form like this:
$pipeline = array(
array(
'$group' => array(
'_id' => array(
'$cond' => array(
array('$lt' => array( '$age', 18 )),
'age_0_17',
array(
'$cond' => array(
array( '$lte' => array( '$age', 25 )),
'age_18_25',
array(
'$cond' => array(
array( '$lte' => array ( '$age', 32 )),
'age_26_32',
'age_Above_32'
)
)
)
)
)
),
'count' => array( '$sum' => 1 )
)
)
);
Also noting that logical comparison operators such as $lt work differently in these stages to their query counterparts. They themselves take an array of arguments being the values to test and compare. They return true/false
based on that comparison, which is the requirement for the first argument to $cond
.
Always handy to have a json_encode
somewhere where you are debugging the form of pipeline queries, as JSON will be the general scope of examples:
echo json_encode( $pipeline, JSON_PRETTY_PRINT ) . "\n";
Which yields the common JSON structure:
[
{ "$group": {
"_id": {
"$cond":[
{ "$lt":["$age",18] },
"age_0_17",
{ "$cond":[
{ "$lte":["$age",25] },
"age_18_25",
{ "$cond":[
{ "$lte":["$age",32] },
"age_26_32",
"age_Above_32"
]}
]}
]
},
"count":{ "$sum": 1 }
}}
]
来源:https://stackoverflow.com/questions/25150635/mongo-age-group-aggregation