I have the db with the following format
Array
(
[_id] => MongoId Object
(
[$id] => 53f4bf0e8db0d31b0ba802df
)
[userSession] => 580929792589634763f964479eee8721
[pageEnteredDate] => 1408548587
[pageLeftDate] => 1408548622
[userName] => User 1
[userId] => 33657
[pageView] => monitoring patients
[pageActions] => []
[pageTag] => 1-3-16-131-315
[timeSpent] => 35
)
Array
(
[_id] => MongoId Object
(
[$id] => 53f3d7008db0d33e61cae841
)
[userSession] => e04e5081c9482654030bacf3c8c90b21
[pageEnteredDate] => 1408488536
[pageLeftDate] => 1408489216
[userName] => user 2
[userId] => 4278
[pageView] => Surgery Staff
[pageActions] => [["BUTTON","Comment",1408488701],["A","Discussion",1408488712]]
[pageTag] => 1-3-5-148
[timeSpent] => 680
)
Array
(
[_id] => MongoId Object
(
[$id] => 53f3d7008db0d33gj1cae841
)
[userSession] => e04e5081c9482654030bahjhc8c90b21
[pageEnteredDate] => 1408488536
[pageLeftDate] => 1408489216
[userName] => user 3
[userId] => 428
[pageView] => Surgery Staff
[pageActions] => [["BUTTON","Comment",1408488701],["A","Discussion",1408488712]]
[pageTag] => 1-3-5-148
[timeSpent] => 680
)
pageEnteredDate is the date that i want to use
I want to group the data by pagetag and day. I mean on one day i should get the same pageTag only once.
So, from those 3 arrays it should display only 2 because 2 have the same pageTag and are on the same day.
Thanks
***code used
$result = $this->collection->aggregate(
array(
array(
'$group' => array(
'_id'=> array( 'pageTag' => '$pageTag','day' => array('$subtract' => array('$pageEnteredDate', 86400))),
'timeSpent' => array( '$sum' => '$timeSpent' ),
'lastView' => array( '$max' => '$pageEnteredDate' )
)
),
array('$skip' => 0),
array('$limit' => 20)
)
);
Your "date" values appear just to be numbers derived from epoch timestamps ( without the milliseconds ). But all you really want to do here is apply $group via the aggregation framework, and a little date math to group by "day":
$result = $collection->aggregate(array(
array(
'$group' => array(
'_id' => array(
'pageTag' => 'pageTag',
'day' => array(
'$subtract' => array(
'$pageEnteredDate',
array('$mod' => array(
'$pageEnteredDate',
60 * 60 * 24
))
)
)
),
'timeSpent' => array( '$sum' => '$timeSpent' ),
'lastView' => array( '$max' => '$pageEnteredDate' )
)
)
));
That basically says to group on both the "pageTag" values and using the "pageEnteredDate" to apply the math that essentially rounds the timestamp to the current day, so all values within the same day are the same.
You haven't said exactly what it is that you want to "group" here, so the examples are given of applying a $sum to the "timeSpent" value and using $max to identify the last timestamp value recorded on that day.
You can use any of the "grouping operators" in this way to suit your needs
Related
I have an array with the following structure:
Array
(
[DigitalAssets] => Array
(
[0] => Array
(
[PartNumber] => 0276S-4
[Link] => https://1ddf4b1b856a39e33863-d785dc0e3b62b5e0ef07f55db00b0659.ssl.cf2.rackcdn.com/Holley/0576s-4.jpg
[AssetTypeCode] => P04
[FileName] => 0576s-4.jpg
[RecordModifiedDate] => 2020-05-13T18:59:10.28
)
[1] => Array
(
[PartNumber] => 0437S-4
[Link] => https://1ddf4b1b856a39e33863-d785dc0e3b62b5e0ef07f55db00b0659.ssl.cf2.rackcdn.com/Holley/0437s-4.jpg
[AssetTypeCode] => P04
[FileName] => 0437s-4.jpg
[RecordModifiedDate] => 2020-05-13T18:59:11.687
)
[2] => Array
(
[PartNumber] => 0574S-4
[Link] => https://1ddf4b1b856a39e33863-d785dc0e3b62b5e0ef07f55db00b0659.ssl.cf2.rackcdn.com/Holley/0574s-4.jpg
[AssetTypeCode] => P04
[FileName] => 0574s-4.jpg
[RecordModifiedDate] => 2020-05-13T18:59:12.593
)
I want to count the total Indexes of array so that I will run loop accordingly. I used Count($array) and Count ($array,RECURSIVE) but it cannot return the correct total number of indexes.
Can only guide that how to do this?
Thanks
If You want to count DigitalAssets direct children You can do this
count($array['DigitalAssets'])
Here are some tests how count should work.
Code is:
$test = array
(
'DigitalAssets' => array
(
0 => array(
'PartNumber' => '0276S-4',
'Link' => 'https://1ddf4b1b856a39e33863-d785dc0e3b62b5e0ef07f55db00b0659.ssl.cf2.rackcdn.com/Holley/0576s-4.jpg',
'AssetTypeCode' => 'P04',
'FileName' => '0576s-4.jpg',
'RecordModifiedDate' => '2020-05-13T18:59:10.28'
),
1 => array(
'PartNumber' => '0437S-4',
'Link' => 'https://1ddf4b1b856a39e33863-d785dc0e3b62b5e0ef07f55db00b0659.ssl.cf2.rackcdn.com/Holley/0437s-4.jpg',
'AssetTypeCode' => 'P04',
'FileName' => '0437s-4.jpg',
'RecordModifiedDate' => '2020-05-13T18:59:11.687'
),
2 => array
(
'PartNumber' => '0574S-4',
'Link' => 'https://1ddf4b1b856a39e33863-d785dc0e3b62b5e0ef07f55db00b0659.ssl.cf2.rackcdn.com/Holley/0574s-4.jpg',
'AssetTypeCode' => 'P04',
'FileName' => '0574s-4.jpg',
'RecordModifiedDate' => '2020-05-13T18:59:12.593'
)
)
);
echo count($test['DigitalAssets'])." ".count($test['DigitalAssets'], 0)." ".count($test['DigitalAssets'], 1);
exit();
Result in my case:
3 3 18
This means taht in my case mode in count is set to 0 by default so i will get only first level counted. If i set mode to 1 i will get all nested items counted as well. This should clear things up for You.
Problem:
I dont know/understand how to check if date and place exists on the same "row" and they exists more then once.
Second, how do i then merge an array
my case MergeArray with ArraySchedule
Code:
$ArraySchedule = array();
while ($data = $stmt -> fetch(PDO::FETCH_ASSOC)) {
$schedules = array(
"id" => $data['id'],
"name" => $data['name'],
"date" => $data['date'],
"time" => $data['time'],
"place_id" => $data['place_id'],
"place" => $data['place'],
);
array_push($ArraySchedule, $schedules);
}
$dupe_array = array();
foreach ($ArraySchedule as $key => $value) {
if(++$dupe_array[$value["date"]] > 1 && ++$dupe_array[$value["place_id"]] > 1 ){
// this statement is wrong, i want something like:
// if date and place_id exists on the same "row" and they exists more then once
}
}
What i want to do:
Check if ArraySchedule contains schedules that have the same date and place,
if there is more than one schedule that has the same date and place_id.
then I want to update ArraySchedule with this structure
$MergeArray = array(
"id" => ArraySchedule['id'],
"name" => array(
"name" => scheduleSameDateAndPlace['name'],
"name" => scheduleSameDateAndPlace['name'],
"name" => scheduleSameDateAndPlace['name'],
),
"date" => $ArraySchedule['date'],
"time" => $ArraySchedule['time'],
"place_id" => $ArraySchedule['place_id'],
"place_name" => $ArraySchedule['place_name'],
),
MergeArray with ArraySchedule?
anyway...
Output I think I want?
Print_r($ArraySchedule)
array(
[0] =>
array(
[id] => 1
[names] => Simon
[date] => 2019-01-02
[time] 18.00
[place_id] => Tystberga Park
[place] => Tystberga
)
[1] =>
array(
[id] => 2
//[names] insted of [name]?
[names] =>
array(
[name] => Vincent
[name] => Angel
[name] => Kim
)
[date] => 2019-02-17
[time] => 13.00
[place_id] => Borås Park
[place] => Borås
)
[2] =>
array(
[id] => 3
// [names] is always an array?
[names] => Caitlyn
[date] => 2019-03-15
[time] 13.00
[place_id] => Plaza Park
[place] => EvPark
)
)
You can use array-reduce. Consider the following:
function mergeByDateAndPlace($carry, $item) {
$key = $item["place_id"] . $item["date"]; // creating key matching exact place and date
if (!isset($carry[$key])) {
$carry[$key]["name"] = $item["name"];
} else {
$carry[$key] = $item;
$item["name"] = [$item["name"]]; // make default array with 1 element so later can be append other names
}
return $carry;
}
Now use it with:
$MergeArray = array_reduce($ArraySchedule, "mergeByDateAndPlace", []);
If you later want to know if there were any duplicate you can just loop on $MergeArray. You can also use array_values if you want to discard the concat keys.
Notice #Nick 2 important comment about saving the first loop and the "time" value that need to be decided. Also notice your desire output contain multi element with the same key ("name") - you need to append them with int key - Array can not have duplicate keys.
Hope that helps!
Here is my data from my database:
var_export($ArraySchedule)
array (
0 => array ( 'id' => '225', 'place_id' => 'Alviks Kulturhus', 'name' => 'BarraBazz', 'date' => '2019-03-19', 'placeadress' => 'Gustavslundsvägen 1', ),
1 => array ( 'id' => '229', 'place_id' => 'Axelhuset Göteborg', 'name' => 'Anders Björk', 'date' => '2019-04-08', 'placeadress' => 'Axel Dahlströms torg 3', ),
2 => array ( 'id' => '230', 'place_id' => 'Axelhuset Göteborg', 'name' => 'Black Jack', 'date' => '2019-04-08', 'placeadress' => 'Axel Dahlströms torg 3', ),
3 => array ( 'id' => '227', 'place_id' => 'Arosdansen Syrianska Kulturcentret', 'name' => 'BarraBazz', 'date' => '2019-05-08', 'placeadress' => 'Narvavägen 90', ),
4 => array ( 'id' => '228', 'place_id' => 'Aspåsnäset', 'name' => 'Blender', 'date' => '2019-05-25', 'placeadress' => 'Aspåsnäset 167', ),
5 => array ( 'id' => '226', 'place_id' => 'Arenan Västervik Resort', 'name' => 'Blender', 'date' => '2019-06-29', 'placeadress' => 'Lysingsvägen', ),
6 => array ( 'id' => '222', 'place_id' => 'Alingsåsparken', 'name' => 'Bendéns', 'date' => '2019-07-16', 'placeadress' => 'Folkparksgatan 3A', ),
7 => array ( 'id' => '223', 'place_id' => 'Alingsåsparken', 'name' => 'Charlies', 'date' => '2019-07-16', 'placeadress' => 'Folkparksgatan 3A', ),
8 => array ( 'id' => '224', 'place_id' => 'Allhuset Södertälje', 'name' => 'Cedrix', 'date' => '2019-07-16', 'placeadress' => 'Barrtorpsvägen 1A', ), )
I want to update the "name" with an array of names everytime that place_id and date are the same.
This is the output I want:
Array (
[0] =>
Array ( [id] => 225 [place_id] => Alviks Kulturhus [name] => BarraBazz [date] => 2019-03-19 [placeadress] => Gustavslundsvägen 1 )
[1] =>
Array ( [id] => 229 [place_id] => Axelhuset Göteborg [name] => Array([0] => Anders Björk [1] => Black Jack ) [date] => 2019-04-08 [placeadress] => Axel Dahlströms torg 3 )
[3] =>
Array ( [id] => 227 [place_id] => Arosdansen Syrianska Kulturcentret [name] => BarraBazz [date] => 2019-05-08 [placeadress] => Narvavägen 90 )
[4] =>
Array ( [id] => 228 [place_id] => Aspåsnäset [name] => Blender [date] => 2019-05-25 [placeadress] => Aspåsnäset 167 )
[5] =>
Array ( [id] => 226 [place_id] => Arenan Västervik Resort [name] => Blender [date] => 2019-06-29 [placeadress] => Lysingsvägen )
[6] =>
Array ( [id] => 222 [place_id] => [Alingsåsparken] [name] => Array([0] => Bendéns [1] => Charlies) [date] => 2019-07-16 [placeadress] => Folkparksgatan 3A )
[8] =>
Array ( [id] => 224 [place_id] => Allhuset Södertälje [name] => Cedrix [date] => 2019-07-16 [placeadress] => Barrtorpsvägen 1A ) )
Here is my updated code
$sql = "SELECT `schedule`.`id`,`schedule`.`place_id`,`schedule`.`name`,`schedule`.`date`,`places`.`placeadress` FROM `schedule` INNER JOIN `places` ON `schedule`.`place_id`=`places`.`place_id` ORDER BY `date`";
$stmt = $db -> prepare($sql);
$stmt -> execute();
$ArraySchedule = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_export($ArraySchedule);
$DatePlace = array();
foreach ($ArraySchedule as $key => $Schedule){
$Arrayquery = "SELECT `schedule`.`id`,`schedule`.`place_id`,`schedule`.`name`,`schedule`.`date`,`places`.`placeadress` FROM `schedule` INNER JOIN `places` ON `schedule`.`place_id`=`places`.`place_id` WHERE `schedule`.`date`= :date_ AND `schedule`.`place_id` = :place_id ORDER BY `date`";
$ArrayStmt = $db->prepare($Arrayquery);
$ArrayStmt -> execute(array(":date_" => $Schedule['date'],":place_id" => $Schedule['place_id']));
//Getting every $Schedule that has the same date and place_id
if($ArrayStmt->rowCount() > 1){
//Here i want two update the name inside
//$ArrayArraySchedule with an array of names
//that has the same place and date?
}
}
print_r($ArraySchedule);
I can get my elements, with the following code :
$lines = $loc->find(
array("loc" =>
array('$near' =>
array('$geometry' =>
array('type' => 'Point', 'coordinates' =>
array(floatval($longitude), floatval($latitude))
),
'$maxDistance' => 10000 //meters
)
)
)
);
This is the results :
Array
(
[_id] => MongoId Object
(
[$id] => 5490003c815289663d8bbd95
)
[name] => My adress
[loc] => Array
(
[type] => Point
[coordinates] => Array
(
[0] => 5.050948
[1] => 45.040419
)
)
)
But now, I need to get the distance from my given point.
Is it possible ?
EDIT :
This is the code used to insert datas :
$loc = $client->localisation->localisation;
$loc->ensureIndex( array("loc" => "2dsphere"));
$loc->insert(
array(
"idobject" => $myValue
"name" => $myName
"loc" => array("type" => "Point", "coordinates" => array($longitude, $latitude))
));
The $near operator does not return a distance along with the returned results. It only orders the documents in the response.
Under the PHP driver the easiest form is to use the $geoNear aggregation pipeline stage instead. This allows you to project a field in the results, or even use it in other pipeline stages:
$loc->aggregate(
array(
array(
'$geoNear' => array(
'near' => array(
'type' => 'Point',
'coordinates' =>array(floatval($longitude), floatval($latitude))
),
'maxDistance' => 1000,
'distanceField' => 'distance',
'spherical' => true
)
)
)
);
There is is a database command form for geoNear as well, but direct command results are often not as nice.
I'm trying to match criteria (cl=1) and then aggregate all the results by month (I've tried year/month/date as well to no luck).
When I run the code below it seems like it works properly, the output shows the months etc, however none of the stats are being added.
The $du field in Mongo is a MongoDate object.
Does anyone have any idea what I'm doing wrong?
See very bottom for a code snippet that is searched by date and returns a result.
$result = $collection->aggregate(
array(
array('$match' => array(
'cl' => $app_id) # application id, int such as "2"
),
array('$project' => array(
//'year' => array('$year' => '$du'),
'month' => array('$month' => '$du'),
//'week' => array('$week' => '$du'),
)),
array('$group' =>
array(
'_id' => array(
'month' => '$month',
),
'i' => array('$sum' => '$vs.i'),
'r' => array('$sum' => '$vs.r'),
'u' => array('$sum' => '$vs.u'),
)
),
array(
'$sort' => array(
'_id' => -1
)
),
array(
'$limit' => 14
)
)
);
Output:
Array
(
[result] => Array
(
[0] => Array
(
[_id] => Array
(
[month] => 10
)
[i] => 0
[r] => 0
[u] => 0
)
[1] => Array
(
[_id] => Array
(
[month] => 9
)
[i] => 0
[r] => 0
[u] => 0
)
.......
working - searching by date
$start = new MongoDate(strtotime("2012-10-01 00:00:00"));
$end = new MongoDate(strtotime("2013-10-15 00:00:00"));
$cursor = $collection->find(array("du" => array('$gt' => $start, '$lte' => $end)));
while ($cursor->hasNext()) {
$document = $cursor->getNext();
print_r($document);exit;
}
# RESPONSE
Array
(
[_id] => MongoId Object
(
[$id] => 51acbfd33dd49497848a8e5b
)
[cl] => 1
[du] => MongoDate Object
(
[sec] => 1370275795
[usec] => 0
)
[vs] => Array
(
[i] => 11
[u] => 1
)
)
The stats aren't there because you haven't chosen to project them. Project gives you _id by default, but anything else you want must be specified.
You'll need something like this instead of your current $project:
array('$project' => array(
'month' => array('$month' => '$du'),
'vs' => 1
))
I have 2 arrays, each with a date string and a string value representing 'amount'. The first array has a row for every day between start_date and end_date, but has nothing for 'amount'. The second array has fewer rows, but has the amount. I need to merge the 2 arrays so that I end up with a row for every day, with an amount for that day, if there is one.
Array 1: every day, no amount:
Array(
[20040601] => Array( [amount] => )
[20040602] => Array( [amount] => )
...
[20100506] => Array( [amount] => )
[20100507] => Array( [amount] => )
)
Array 2: unique date for each row, has amount, not an entry for every day:
Array(
[20040618] => Array( [amount] => 19764 )
[20040727] => Array( [amount] => 18008 )
...
[20040925] => Array( [amount] => 5480 )
[20041007] => Array( [amount] => 12522 )
)
Result:
Array(
[20040618] => Array( [amount] => 19764 )
[20040619] => Array( [amount] => )
[20040620] => Array( [amount] => 5967)
[20040621] => Array( [amount] => )
...
[20040625] => Array( [amount] => 5480 )
[20040626] => Array( [amount] => 12522 )
[20040627] => Array( [amount] => 4523 )
)
EDIT: Showing the result array a little better.
Resulting array would include a row for every day, with the corresponding amount for that day, if there is one. So basically, merge on the date key and return the date and amount. I've tried to get merge_array to work but I am losing my date in the process. There has to be a native function to do this without resorting to iterative looping through the array.
I've tried to get merge_array to work
but I am losing my date in the
process.
This is being caused by the conversion of your date string to a numeric type, which causes array_merge() to behave differently. If you use a string key that PHP won't convert to a number, it should do what you want:
$arr1 = array(
'2004-06-01' => array('amount' => null),
'2004-06-02' => array('amount' => null),
'2010-05-06' => array('amount' => null),
'2010-05-07' => array('amount' => null),
);
$arr2 = array(
'2004-06-01' => array('amount' => 50),
'2004-06-02' => array('amount' => 100),
'2010-05-08' => array('amount' => 200),
'2010-05-07' => array('amount' => 250),
);
print_r(array_merge($arr1, $arr2));
array_merge_recursive($array1, $array2);