通过mongodb $ reduce(汇总)过滤列表

时间:2020-06-23 08:06:53

标签: mongodb aggregation-framework

我有一个简单的记录列表(活动供稿):

[
{
    "_id" : "1",
    "body" : "Andrew changed the status to Unstarted",
    "assignedTo" : "User_1"
}
{
    "_id" : "2",
    "body" : "Andrew changed the status to Unstarted",
    "assignedTo" : "User_2"
}
{
    "_id" : "3",
    "body" : "Mike assigned to Andrew",
    "assignedTo" : "User_2"
}
{
    "_id" : "4",
    "body" : "Mike assigned to Andrew",
    "assignedTo" : "User_1"
}
{
    "_id" : "5",
    "body" : "Mike assigned to Andrew",
    "assignedTo" : "User_3"
}
{
    "_id" : "6",
    "body" : "Andrew moved this action to For me",
    "assignedTo" : "User_1"
}
{
    "_id" : "7",
    "body" : "Andrew moved this action to For me",
    "assignedTo" : "User_3"
}
{
    "_id" : "8",
    "body" : "Mike assigned to Andrew, Eric",
    "assignedTo" : "User_1"
}
{
    "_id" : "9",
    "body" : "Mike assigned to Andrew, Eric",
    "assignedTo" : "User_3"
} 
]

当我从数据库获得此列表时,我通过JS对其进行了过滤: (过滤所有连续的重复活动,因为为每个分配/参与的用户都创建了一个活动供稿)

const ids = receivedList.reduce((acc, curr, idx, src) => {
      // previous record/element
      const prev = src[idx - 1];

      const cond = (
       idx === 0 ||
       curr.body !== prev.body ||
       (curr.body === prev.body && curr.assignedTo === prev.assignedTo)
      );

      if (cond) {
        return acc.concat(curr._id);
      }
      return acc;
    }, []);

如何通过mongodb聚合进行相同的减少/过滤?

1 个答案:

答案 0 :(得分:0)

我自己找到了答案:

aggregate([
      {
        $match: {
          // your match
        },
      },
      { $sort: { body: 1 } },
      {
        $project: {
          body: 1,
          assignedTo: 1,
        },
      },
      { $group: { _id: null, matchedFeeds: { $push: '$$ROOT' } } },
      {
        $project: {
          result: {
            $reduce: {
              input: '$matchedFeeds',
              initialValue: {
                previousFeed: {},
                filteredFeeds: [],
              },
              in: {
                previousFeed: '$$this',
                filteredFeeds: {
                  $cond: {
                    if: {
                      $or: [
                        { $ne: ['$$this.body', '$$value.previousFeed.body'] },
                        {
                          $and: [
                            { $eq: ['$$this.assignedTo', '$$value.previousFeed.assignedTo'] },
                            { $eq: ['$$this.body', '$$value.previousFeed.body'] },
                          ],
                        },
                      ],
                    },
                    then: { $concatArrays: ['$$value.filteredFeeds', ['$$this']] },
                    else: '$$value.filteredFeeds',
                  },
                },
              },
            },
          },
        },
      },
      {
        $project: {
          feedList: '$result.filteredFeeds',
        },
      },
    ])