【问题标题】:Mongodb - query and group by status for documentsMongodb - 按文档状态查询和分组
【发布时间】:2019-12-13 23:03:01
【问题描述】:

我有猫鼬模型 - 用户和工单

用户:

//Create schema
const userSchema = new Schema({
    title: String,
    f_name: {
        type: String,
        required: true
    },
    m_name: String,
    l_name: {
        type: String,
        required: true
    },
...
}

评论:

//Create schema
const commentSchema = new Schema({
    title: String,
    ticket_id: String,
    user: {
        type: Schema.Types.ObjectId,
        ref: 'User'
    },
    status: {
        type: String,
        enum: ['New', 'Open', 'Pending', 'Suspended', 'Solved']
    },
    ...
}

我必须根据状态获取用户列表以及 cmets 计数: 示例:

{
  'f_name': 'XYZ',
  ...,
  status_data: {
    [
      {
        'status': 'New',
        'count': 3
      },
      {
        'status': 'Solved',
        'count': 3
      },
      {
        'status': 'Suspended',
        'count': 3
      }
    ]
  }
}

目前我正在尝试:

User.aggregate([
        {
            $lookup: {
                from: 'tickettests',
                localField: '_id',
                foreignField: 'assigned_to',
                as: 'tickets_doc'
            }
        },
        {
            $unwind: {
                path: '$tickets_doc'
            }
        },
        {
            $group: {
                _id: {
                    _id: '$_id',
                    status: '$tickets_doc.status'
                },
                user_id: {$first: '$_id'},
                f_name: {$first: '$f_name'},
                l_name: {$first: '$l_name'},
                createdAt: {$first: '$createdAt'},
                updatedAt: {$first: '$updatedAt'},
                count: {
                    $sum: 1
                }
            }
        }
    ])
    .then(ticketPromisesRes => {
        res.status(200).json(ticketPromisesRes);
    })
    .catch(err => {
        logger.error(err);
        res.status(500).json({message: 'Cannot get contact list with tickets'})
    })

数据像往常一样聚合,有重复的用户,但它的状态和数量是唯一的,我试图让它像上面给出的响应一样,

目前的回应:

{
        "_id": {
            "_id": "xxxxx",
            "status": "New"
        },
        "user_id": "xxxxx",
        "f_name": "XYZ",
        "l_name": "ZXC",
        "createdAt": "2019-12-07T04:43:03.839Z",
        "updatedAt": "2019-12-07T04:45:59.322Z",
        "count": 2
    },
    {
        "_id": {
            "_id": "xxxxxx",
            "status": "Suspended"
        },
        "user_id": "xxxxxx",
        "f_name": "ASD",
        "l_name": "DSA",
        "createdAt": "2019-12-07T04:28:13.616Z",
        "updatedAt": "2019-12-07T04:37:03.737Z",
        "count": 1
    },
    {
        "_id": {
            "_id": "xxxxxxx",
            "status": "Suspended"
        },
        "user_id": "xxxxxxx",
        "f_name": "XYZ",
        "l_name": "ZXC",
        "createdAt": "2019-12-07T04:43:03.839Z",
        "updatedAt": "2019-12-07T04:45:59.322Z",
        "count": 1
    },

【问题讨论】:

    标签: mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    您可以使用以下 2 级组聚合。

    Playground

    db.users.aggregate([
      {
        $lookup: {
          from: "tickets",
          localField: "user_id",
          foreignField: "user",
          as: "tickets_doc"
        }
      },
      {
        $unwind: {
          path: "$tickets_doc"
        }
      },
      {
        $group: {
          _id: {
            user: "$user_id",
            ticket: "$tickets_doc.status"
          },
          user: {
            "$first": "$$ROOT"
          },
          statusTotal: {
            $sum: 1
          }
        }
      },
      {
        $group: {
          _id: {
            userId: "$_id.user",
            f_name: "$user.f_name",
            l_name: "$user.l_name"
          },
          status_data: {
            $push: {
              status: "$_id.ticket",
              count: "$statusTotal"
            }
          }
        }
      },
      {
        "$replaceRoot": {
          "newRoot": {
            $mergeObjects: [
              "$_id",
              {
                "status_data": "$status_data"
              }
            ]
          }
        }
      }
    ])
    

    示例文件:

    db={
      "users": [
        {
          "user_id": "user1",
          "f_name": "user1 firstname",
          "l_name": "user1 lastname"
        },
        {
          "user_id": "user2",
          "f_name": "user2 firstname",
          "l_name": "user2 lastname"
        }
      ],
      "tickets": [
        {
          "title": "comment1",
          "user": "user1",
          "status": "New"
        },
        {
          "title": "comment2",
          "user": "user1",
          "status": "New"
        },
        {
          "title": "comment3",
          "user": "user2",
          "status": "New"
        },
        {
          "title": "comment4",
          "user": "user1",
          "status": "Open"
        },
        {
          "title": "comment5",
          "user": "user2",
          "status": "Open"
        },
        {
          "title": "comment6",
          "user": "user2",
          "status": "Pending"
        },
        {
          "title": "comment7",
          "user": "user2",
          "status": "Pending"
        }
      ]
    }
    

    输出:

    [
      {
        "f_name": "user2 firstname",
        "l_name": "user2 lastname",
        "status_data": [
          {
            "count": 2,
            "status": "Pending"
          },
          {
            "count": 1,
            "status": "Open"
          },
          {
            "count": 1,
            "status": "New"
          }
        ],
        "userId": "user2"
      },
      {
        "f_name": "user1 firstname",
        "l_name": "user1 lastname",
        "status_data": [
          {
            "count": 2,
            "status": "New"
          },
          {
            "count": 1,
            "status": "Open"
          }
        ],
        "userId": "user1"
      }
    ]
    

    【讨论】:

      【解决方案2】:

      我认为您需要将 $lookup 与管道一起使用:

      $lookup: {
        from: 'tickettest',
        let: { userId: '$_id' },
        pipeline: [{
          $match: {
            $expr: {
              $eq: ['$assignedTo', '$$userId']
            }
          },
          {
            $project: {
              status: 1,
            }
          },
          {
            $group: { 
              _id: '$status',
              count: {
                $sum: 1
              }
            }
          },
        }],
        as: 'status_data'
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-24
        • 2016-09-29
        • 1970-01-01
        • 1970-01-01
        • 2021-05-19
        • 1970-01-01
        相关资源
        最近更新 更多