在Laravel MongoDB中获取员工列表及每人完成的任务数
问题描述
我正在使用Laravel MongoDB库(原Jenssegers MongoDB库),现有employees集合和task集合,其中task集合的employees字段是员工ObjectId数组。原本的查询是获取状态为活跃、未删除的员工列表,现在需要修改查询,让每个员工数据附带已完成任务的数量,期望输出格式如下:
{ _id : {$oid: 2ndkj3720eA83b24}, name : 'Employee1', task_completed: 23 }
集合结构
employees集合
{ _id : {$oid: 2ndkj3720eA83b24}, name : 'Employee1', status : 'a', deleted_at : null }
task集合
{ _id : {$oid: 893jfo2ok01398190}, name : 'Task 1', employees : [ {$oid: ae2nvg6788eA83b24}, {$oid: be09gh56701398190}, {$oid: bf0e28bfi45202bc0} ], complete_status : 'c', status : 'a', deleted_at : null }
原查询代码
$employeeQuery = Employee::where(array( 'status' => Globals::SMALL_CHAR_ACTIVE, 'deleted_at' => NULL )); if($employeeQuery->count() > 0) { $employeeListing = $employeeQuery->get()->toArray(); }
解决方案
方法一:使用MongoDB聚合管道(性能最优)
直接通过聚合管道完成过滤、关联和统计,适合数据量较大的场景:
$employeeListing = Employee::raw(function ($collection) { return $collection->aggregate([ // 过滤活跃且未删除的员工 [ '$match' => [ 'status' => Globals::SMALL_CHAR_ACTIVE, 'deleted_at' => null ] ], // 关联tasks集合,筛选已完成的有效任务 [ '$lookup' => [ 'from' => 'tasks', 'localField' => '_id', 'foreignField' => 'employees', 'as' => 'completed_tasks', 'pipeline' => [ [ '$match' => [ 'complete_status' => 'c', // 已完成状态标识 'status' => 'a', 'deleted_at' => null ] ] ] ] ], // 统计已完成任务数量 [ '$addFields' => [ 'task_completed' => ['$size' => '$completed_tasks'] ] ], // 保留所需字段 [ '$project' => [ 'name' => 1, 'task_completed' => 1 ] ] ])->toArray(); });
阶段说明
$match:筛选出符合条件的员工,和原查询逻辑一致。$lookup:关联tasks集合,通过员工_id匹配任务的employees数组,同时在子管道中过滤已完成、活跃且未删除的任务。$addFields:用$size函数统计关联到的任务数组长度,生成task_completed字段。$project:只保留_id(默认保留)、name和task_completed字段,匹配期望输出格式。
方法二:通过模型关联+withCount
如果习惯使用Eloquent关联语法,可以在模型中定义关联后使用withCount统计:
第一步:在Employee模型中定义关联
public function completedTasks() { return $this->belongsToMany(Task::class, null, 'employees', '_id') ->where('complete_status', 'c') ->where('status', 'a') ->whereNull('deleted_at'); }
第二步:执行查询
$employeeListing = Employee::where('status', Globals::SMALL_CHAR_ACTIVE) ->whereNull('deleted_at') ->withCount(['completedTasks as task_completed']) ->select('_id', 'name', 'task_completed') ->get() ->toArray();
关联参数说明
belongsToMany的第二个参数填null,因为这里没有单独的中间表,直接通过task集合的employees数组关联。- 第三个参数
employees是task集合中存储员工ID的字段名。 - 第四个参数
_id是当前Employee模型的主键字段。
内容的提问来源于stack exchange,提问作者Saswat
相关产品推荐
相关产品推荐

