You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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();
});

阶段说明

  1. $match:筛选出符合条件的员工,和原查询逻辑一致。
  2. $lookup:关联tasks集合,通过员工_id匹配任务的employees数组,同时在子管道中过滤已完成、活跃且未删除的任务。
  3. $addFields:用$size函数统计关联到的任务数组长度,生成task_completed字段。
  4. $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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 22:17:03