mongoDB PHP aggregate collection by date and sum field per date - php

I am attempting to output an array of dates grouped by date with a sum of a field called minutes_numeric.
My current query is:
return $this->db->Work->aggregate(array(
array(
'$match' => array(
'date' => array('$gt' => $start, '$lt' => $end)
)
),
array(
'$project' => array(
'year' => array('$year' => '$date' ),
'month' => array('$month' => '$date' ),
'day' => array('$dayOfMonth' => '$date'),
),
),
array(
'$group' => array(
'_id' => array('year' => '$year', 'month' => '$month', 'day' => '$day'),
'minutes_numeric' => array('$sum' => 1)
),
),
array(
'$sort' => array(
'_id' => 1
),
),
array(
'$limit' => 30
)
));
Which outputs:
{
result: [
{
_id: {
year: 2013,
month: 12,
day: 4
},
minutes_numeric: 40
},
{
_id: {
year: 2013,
month: 12,
day: 11
},
minutes_numeric: 127
},
{
_id: {
year: 2013,
month: 12,
day: 12
},
minutes_numeric: 108
}
],
ok: 1
}
Which is great, however the minutes_numeric represents the number of rows for that day, so I changed the $group clause:
array(
'$group' => array(
'_id' => array('year' => '$year', 'month' => '$month', 'day' => '$day'),
'minutes_numeric' => array('$sum' => '$minutes_numeric')
),
),
Which then changes the sum (minutes_numeric) to 0 and not an actual sum.
I'm unsure why my sum is going wrong, any help is greatly appreciated
Edit,
If I update the $project to include minutes_numeric then the sum seems to exclude the $match parameters
array(
'$project' => array(
'year' => array('$year' => '$date' ),
'month' => array('$month' => '$date' ),
'day' => array('$dayOfMonth' => '$date'),
'minutes_numeric' => 1
),
),
array(
'$group' => array(
'_id' => array('year' => '$year', 'month' => '$month', 'day' => '$day'),
'minutes_numeric' => array('$sum' => '$minutes_numeric')
),
)

If this is you current query
return $this->db->Work->aggregate(array(
array(
'$match' => array(
'date' => array('$gt' => $start, '$lt' => $end)
)
),
array(
'$project' => array(
'year' => array('$year' => '$date' ),
'month' => array('$month' => '$date' ),
'day' => array('$dayOfMonth' => '$date'),
'minutes_numeric' => 1
),
),
array(
'$group' => array(
'_id' => array('year' => '$year', 'month' => '$month', 'day' => '$day'),
'minutes_numeric' => array('$sum' => '$minutes_numeric')
),
),
array(
'$sort' => array(
'_id' => 1
),
),
array(
'$limit' => 30
)
));
then the only way your $match parameters are "ignored" and the results are not as you expect is probably because they are wrong. Try checking the values of $start and $end, because the query you are using seems correct.
In case that is not the problem please update your question with the results of your current query. (Also update your query if it is different than the one in my answer)

Related

Add values from multidimensional array to another array

Hello good morning wherever you are :D, i have a lil problem, i have this code of arrays
$arrayToView is the info of every single user that i want.
$tagsArray are only tags that use every user but i need to merge all the info something like the last array...
$arrayToView = array(
'IVOFACUNDO' = array(
'mails' => 3,
'contacts' => 34,
'blocked' => 23
),
'ESRAYCU' = array(
'mails' => 23,
'contacts' => 124,
'blocked' => 44
)
)
And i have another one like this
$tagsArray= array(
'IVOFACUNDO' = array(
'14' => array(
'id' => 14,
'name' => 'php',
'value' => 1
),
'15' => array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
),
'ESRAYCU' = array(
'1' => array(
'id' => 1,
'name' => 'python',
'value' => 1
),
'15'=> array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
)
)
so the question is how i can merge both arrays obviously respectively with the same admin something like this
$arrayToView = array(
'IVOFACUNDO' = array(
'mails' => 3,
'contacts' => 34,
'blocked' => 23,
'tags' => array(
'14' => array(
'id' => 14,
'name' => 'php',
'value' => 1
),
'15' => array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
)
),
'ESRAYCU' = array(
'mails' => 23,
'contacts' => 124,
'blocked' => 44,
'tags' => array(
'1' => array(
'id' => 1,
'name' => 'python',
'value' => 1
),
'15'=> array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
)
)
)
The key 'tags' need to be created in the merge of every iteration to add and get one array with all the values, how i can do this?
You can try this snippet.
foreach($arrayToView as $key => $arr){
if(array_key_exists($key, $tagsArray)){
$arrayToView[$key]['tags'] = $tagsArray[$key];
}
}
echo '<pre>';print_r($arrayToView);echo '</pre>';
Use php inbuilt function
$result_Arr = array_merge_recursive($arrayToView,$tagsArray);
<?php
$arrayToView = array(
'IVOFACUNDO' => array(
'mails' => 3,
'contacts' => 34,
'blocked' => 23
),
'ESRAYCU' => array(
'mails' => 23,
'contacts' => 124,
'blocked' => 44
)
);
$tagsArray= array(
'IVOFACUNDO' => array(
'14' => array(
'id' => 14,
'name' => 'php',
'value' => 1
),
'15' => array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
),
'ESRAYCU' => array(
'1' => array(
'id' => 1,
'name' => 'python',
'value' => 1
),
'15'=> array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
)
);
foreach($arrayToView as $key => $value){
if(isset($tagsArray[$key])){
$arrayToView[$key]['tags'] = array();
foreach($tagsArray[$key] as $key2 => $value2){
$arrayToView[$key]['tags'][$key2] = $tagsArray[$key][$key2];
}
}
}
echo'<pre>';
print_r($arrayToView);
echo'</pre>';
?>

Return partial matches from multidimensional array search in PHP

I'm very new to PHP so any help here is greatly appreciated. I have an array that I need to search and return partial and exact matches. Here's the array and where I've started code-wise:
$employeeList = array(
array(
'action' => false,
'title' => '2015 Performance Appraisal - Basille, Victor P.',
'type' => 'Employee Assessment',
'status' => 'Evaluate',
'date' => 'Dec 12, 2015',
'actions' => array('Start','Delete','View Progress','Manage Rater and Peers','Print'),
'employeeName' => 'Basille, Victor P.',
'employeeProgress' => 0,
'employeeStatus' => 'Not Yet Started',
'raterName' => 'Crane, Davy L.',
'raterProgress' => 0,
'raterStatus' => 'Not Yet Started',
'peers' => 3,
'peersComplete' => 0
),
array(
'action' => true,
'title' => '2015 Performance Appraisal - Bradford, Julie D.',
'type' => 'Employee Assessment',
'status' => 'Evaluate',
'date' => 'Dec 12, 2015',
'actions' => array('Resume','Reset','View Progress','Delete','Manage Rater and Peers','Print'),
'employeeName' => 'Bradford, Julie D.',
'employeeProgress' => 10,
'employeeStatus' => 'In Progress',
'raterName' => 'Crane, Davy L.',
'raterProgress' => 60,
'raterStatus' => 'In Progress',
'peers' => 3,
'peersComplete' => 1
),
array(
'action' => false,
'title' => '2015 Performance Appraisal - Fiedler, Joanne M.',
'type' => 'Employee Assessment',
'status' => 'Review',
'date' => 'Dec 12, 2015',
'actions' => array('View','Reset','Revert','View Progress','Print'),
'employeeName' => 'Fiedler, Joanne M.',
'employeeProgress' => 100,
'employeeStatus' => 'Submitted',
'raterName' => 'Fay, Lester P.',
'raterProgress' => 100,
'raterStatus' => 'Submitted',
'peers' => 3,
'peersComplete' => 3
)
);
$search_term = 'Victor';
$key = array_search($search_term, array_column($employeeList, 'title'));
This works great, except it only works for exact matches of the 'title'. How can I make this return partial matches as well?
Thanks.
what you need is preg_grep() which searchs the array for patern matching elements and returns them in an array.
http://php.net/manual/en/function.preg-grep.php
$result_array = preg_grep("/{$keyword}/i",$employeeList)

Merge arrays made in a loop PHP

I have a array that, 3 repeats from the same week, but 3 differents users that have your totals separately:
array
0 =>
array
'week' => '1'
'user' => 'Oswaldo Aranha'
'totals' => 'value'
1 =>
array
'week' => '1'
'user' => 'Protogenes'
'totals' => 'value'
2 =>
array
'week' => '1'
'user' => 'Rego Barros'
'totals' => 'value'
3 =>
array
'week' => '2'
'user' => 'Oswaldo Aranha'
'totals' => 'value'
4 =>
array
'week' => '2'
'user' => 'Protogenes'
'totals' => 'value'
5 =>
array
'week' => '2'
'user' => 'Rego Barros'
'totals' => 'value'
...
I wanna to unify the week in one array, with the 3 users and your totals. Like this:
array
0 =>
array
'week' => '1'
'Oswaldo Aranha' => 'value'
'Protogenes' => 'value'
'Rego Barros' => 'value'
1 =>
array
'week' => '2'
'Oswaldo Aranha' => 'value'
'Protogenes' => 'value'
'Rego Barros' => 'value'
2 =>
array
'week' => '3'
'Oswaldo Aranha' => 'value'
'Protogenes' => 'value'
'Rego Barros' => 'value'
...
I'm trying using array_merge(), array_combine(), array_whatever() but doesn' work. How i do that?
you can use array_merge();
$arr=array_merge ( $array[0],$array[1] ,$array[3]);
i hope this will help you :)
for extra info this link will help you :
http://php.net/manual/en/function.array-merge.php
$array = [
[
'week' => '1',
'user' => 'Oswaldo Aranha',
'totals' => 'value'
],
[
'week' => '1',
'user' => 'Protogenes',
'totals' => 'value'
],
[
'week' => '1',
'user' => 'Rego Barros',
'totals' => 'value'
],
[
'week' => '2',
'user' => 'Oswaldo Aranha',
'totals' => 'value',
],
[
'week' => '2',
'user' => 'Protogenes',
'totals' => 'value'
]
];
function combineWeeks($array) {
$results = [];
for($i = 0;$i < count($array);$i++) {
$results[$array[$i]['week']][$array[$i]['user']] = $array[$i]['totals'];
$results[$array[$i]['week']]['week'] = $array[$i]['week'];
}
$combined = [];
foreach($results as $key => $value) {
$combined[] = $results[$key];
}
return $combined;
}
Usage:
$combinedArray = combineWeeks($array);
print_r($combinedArray);
output:
Array
(
[0] => Array
(
[Oswaldo Aranha] => value
[week] => 1
[Protogenes] => value
[Rego Barros] => value
)
[1] => Array
(
[Oswaldo Aranha] => value
[week] => 2
[Protogenes] => value
)
)
I think there is no php-function doing it for you. Just do it your own:
$in = $array;
$out = [];
foreach ($in as $curIn) {
if ( ! isset ($out[$curIn["week"]])) {
$out[$curIn["week"]] = [];
}
$out[$curIn["week"]][$curIn["user"]] = $curIn["totals"];
}
That's it.

Convert MongoDB console aggregate to php with array

i am failing to convert the following mongoDB console command:
db.customers.aggregate( [
{ $group : {
_id: {
year : { $year: "$since" },
month : { $month: "$since" }
},
count: { $sum: 1 }
}
}]
);
which works into php
$customers->aggregate(array(
'$group' => array(
'_id' => array( 'year' => array('$year' => '$since'),
'month' => array('$month' => '$since')
)
),
array(
'count' => array( '$sum' => 1 )
),
)
);
which returns exception: A pipeline stage specification object must contain exactly one field.
also already tried '"$since"' with no luck
The count field must be a part of the group.
$customers->aggregate(array(
'$group' => array(
'_id' => array( 'year' => array('$year' => '$since'),
'month' => array('$month' => '$since')
),
'count' => array( '$sum' => 1 )
)
));

MongoDB aggregate with PHP - group by on date

I am using an aggregate in MongoDB with PHP. The code looks like:
$results = $c->aggregate(array(
array(
'$project' => array(
'day' => array('$dayOfYear' => '$executed')
),
),
array(
'$group' => array(
'_id' => array('day' => '$day'),
'count' => array('$sum' => 1)
),
),
array(
'$sort' => array(
'_id' => 1
),
),
array(
'$limit' => 30
)
));
The problem with this, is that $dayOfYear does not sort correctly, because it sorts 2 then 3 then 345, 346... I need it to be date ascending. So, basically instead of simply doing $dayOfYear I need something like $year-$month-$dayOfMonth.
Unfortunately this does not work. Any ideas?
Thanks.
You can project those parts out and then group on them to enable you to group on the whole date:
$results = $c->aggregate(array(
array(
'$project' => array(
'year' => array('$year' => '$executed' ),
'month' => array('$month' => '$executed' ),
'day' => array('$dayOfMonth' => '$executed')
),
),
array(
'$group' => array(
'_id' => array('year' => '$year', 'month' => '$month', 'day' => '$day'),
'count' => array('$sum' => 1)
),
),
array(
'$sort' => array(
'_id.year' => 1,
'_id.month' => 1,
'_id.day' => 1
),
),
array(
'$limit' => 30
)
));
Something like that should do the trick allowing you to sort on, as you stated: $year-$month-$dayOfMonth.
You shouldn't sort on the entire _id because you've set that up to contain an object (which can sort oddly), so change your $sort to this instead to specifically sort by day of year:
'$sort' => array(
'_id.day' => 1
),

Categories