Mongoose / Mongo通过createdAt计算引用数组中的对象

时间:2018-05-03 13:52:11

标签: node.js mongodb mongoose aggregation

在我的用户集上,我有两个这样的字段:

  assignedTickets: [
    {
      type: mongoose.Schema.ObjectId,
      ref: 'Ticket',
      index: true,
    },
  ],
  resolvedTickets: [
    {
      type: mongoose.Schema.ObjectId,
      ref: 'Ticket',
      index: true,
    },
  ],

对于这些字段中的每一个,我都试图根据每个对象的创建日期来计算对象。例如,对于2018-05-03,我想知道在该日期创建了多少票。

我试过这个:

const start = new Date();
start.setHours(0, 0, 0, 0);
const end = new Date();
end.setHours(23, 59, 59, 999);

userSchema.statics.assignedToday = function () {
  return this.aggregate([
    {
      $lookup: {
        from: 'tickets', localField: '_id', foreignField: 'assignee_id', as: 'tickets',
      },
    },
    { $unwind: '$tickets' },
    { $match: { createdAt: { $gte: start, $lt: end } } },
    {
      $group: {
        _id: {
          year: { $year: '$createdAt' },
          month: { $month: '$createdAt' },
          day: { $dayOfMonth: '$createdAt' },
        },
        count: { $sum: 1 },
      },
    },
  ]);
};

但我只收到一个空数组[]

如果我注释掉管道的$ match部分,我得到:

[
  {
    "_id": {
      "year": 2018,
      "month": 5,
      "day": 2
    },
    "count": 178
  }
]

但这是所有门票的总数(不仅仅是已分配),数据将在5月2日(即创建故障单集合的日期)回来。

以下是用户文档的示例:

{
  "assignedTickets": [
    "5ae9c2d59c7fcb540cca0b9e",
    "5ae9c3649c7fcb540cca0ba0",
    "5ae9c3849c7fcb540cca0ba2",
    ...
  ],
  "resolvedTickets": [
    "5ae9c2d59c7fcb540cca0b9d",
    "5ae9c2d59c7fcb540cca0b9e",
    "5ae9c3299c7fcb540cca0b9f",
    ...
  ],
  "_id": "5ae763a6ed455639802e8f1a",
  "firstName": "NAME",
  "lastName": "LASTNAME",
  "email": "EMAIL",
  "createdAt": "2018-04-30T18:42:46.582Z",
  "updatedAt": "2018-05-03T15:29:13.955Z",
  "__v": 0,
}

以下是故障单文档的示例:

{
  "_id": "5ae9c2d59c7fcb540cca0b9e",
  "ticket_id": 119472,
  "type": "resolved",
  "status": "Solved",
  "assignee_email": "EMAIL",
  "createdAt": "2018-05-01T13:53:25.639Z",
  "updatedAt": "2018-05-03T04:06:22.852Z",
  "__v": 0,
  "assignee_id": "5ae763a6ed455639802e8f1a"
}

1 个答案:

答案 0 :(得分:0)

我能够找出正确的语法来正确返回结果:

const start = new Date().setHours(0, 0, 0, 0);
const end = new Date().setHours(23, 59, 59, 999);

userSchema.statics.getAssigned = function () {
  return this.aggregate([
    {
      $lookup: {
        from: 'tickets',
        localField: 'assignedTickets',
        foreignField: '_id',
        as: 'assigned_tickets',
      },
    },
    { $unwind: '$assigned_tickets' },
    { $match: { 'assigned_tickets.createdAt': { $gte: new Date(start), $lt: new Date(end) } } },
    {
      $group: {
        _id: {
          year: { $year: '$assigned_tickets.createdAt' },
          month: { $month: '$assigned_tickets.createdAt' },
          day: { $dayOfMonth: '$assigned_tickets.createdAt' },
          _id: '$assigned_tickets.assignee_id' },
        },
        count: {
          $sum: 1,
        },
      },
    },
  ]);
};

我原来的功能有一些问题。

首先,在查找时,我引用了localField的_id字段,但应该是assignedTickets(专门用于获取已分配的票证),以及foreignField assignee_id应该是_id

第二个问题是传递到$ match阶段的日期,this SO question help me answer

最后,$ match阶段需要引用$ lookup阶段的assigned_tickets别名,mandar帮助我意识到这一点。