我正在为 MongoDB 使用 Laravel 5.1 和 jenssegers/laravel-mongodb 包。我正在尝试在 MongoDB 中执行此操作:
$offers = Offer::select(DB::raw('DATE(created_at) as date'), DB::raw('count(created_at) as cnt'))->groupBy('date')->get();
使用此网址中的示例:https://github.com/jenssegers/laravel-mongodb/issues/361 我试过这个:
// in Offer.php
public function scopePostedJobs($query){
$q = $query->groupBy('created_at');
$q->getQuery()->aggregate = [ 'function' => 'count', 'columns' => [ 'created_at' ] ];
return $q;
}
// in controller
$postedJobs = Offer::postedJobs()->get();
这个示例无法正常工作,因为它按完整时间戳分组,而我只需要日期,不需要时间。那么如何按created_at进行分组但仅使用日期而不使用时间呢?
感谢@BrentR 和@chridam 我找到了这个解决方案:
$postedJobs = Offer::raw()->aggregate(array(
array(
'$group' => array(
'_id' => array(
'yearMonthDay' => array(
'$dayOfYear' => '$created_at'
)
),
'count' => array( '$sum' => 1 )
)
)
));
由于某种原因 $dateToString 对我不起作用,所以我使用了 @BrentR 的建议并且它起作用了
您可以使用 mongo 聚合与 $dayOfYear 运算符来实现此分组。
参见https://docs.mongodb.org/v3.0/reference/operator/aggregation/dayOfYear/
为了获得更好的性能,请使用底层 MongoDB 驱动程序的聚合框架方法,因为这使用 MongoDB 服务器上的本机代码,而不是基本上包装了 mapReduce 方法的
.groupBy()
方法。
$dateToString
在 $group
管道中,根据用户指定的格式将日期对象转换为字符串
db.collectionName.aggregate([
{
"$group": {
"_id": {
"yearMonthDay": { "$dateToString": { format: "%Y-%m-%d", date: "$accesstime" } }
},
"count": { "$sum": 1 }
}
}
]);
等效的 Laravel 示例实现:
$postedJobs = DB::collection('collectionName')->raw(function($collection)
{
return $collection->aggregate(array(
array(
"$group" => array(
"_id" => array(
"yearMonthDay" => array(
"$dateToString" => array(
format => "%Y-%m-%d",
date => "$created_at"
)
)
),
"count" => array( "$sum" => 1 )
)
)
));
});