Mongo聚合。将匹配多个条件的数组元素作为新字段。 (包括复制)

时间:2020-03-26 07:53:33

标签: mongodb

当前查询:https://mongoplayground.net/p/mCD3vLoGG1q

上下文:用户对建议投赞成票或反对票。建议和投票在他们自己的收藏中。我正在使用$lookup来获得建议的所有票,它在汇总过程中变成一个数组。

我想要每个建议的总投票数,还要2个特定用户的投票数据。

  1. 已登录的用户
  2. 广播用户。

此“投票数据”可以是简单的布尔值(用户是否赞成),也可以是数组元素本身(首选)。我只需要知道他们是如何对建议投票的。

当前结果

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    // WRONG. The broadcaster downvoted.
    "broadcasterUpvoted": true, 
    "hasUpvoted": true,
    "id": "sid",
    "votesLength": 2
  }
]

所需结果

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
     // CORRECT!!!
    "broadcasterUpvoted": false,
    "hasUpvoted": true,
    "id": "sid",
    "votesLength": 2
  }
]

获取数组元素可能很有用,因此此结果也很好。

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "broadcasterVote": {
      "suggestionId": "sid",
      "voteType": "downVote",
      "user": {
        "id": "broadcasterUserId"
      }
    },,
    "loggedInUserVote": {
      "suggestionId": "sid",
      "voteType": "upVote",
      "user": {
        "id": "loggedInUser"
      }
    },
    "id": "sid",
    "votesLength": 2
  }
]

编辑:另一个问题是,如何使votesLength = (totalUpVotes - totalDownVotes)而不只是sizeOfVotesArray

1 个答案:

答案 0 :(得分:2)

尝试这个:

db.suggestions.aggregate([
  {
    $match: {
      id: "sid"
    }
  },
  {
    $lookup: {
      from: "votes",
      localField: "id",
      foreignField: "suggestionId",
      as: "votes"
    }
  },
  {
    $addFields: {
      hasUpvoted: {
        $filter: {
          input: "$votes",
          cond: { $eq: [ "apiCallUserId", "$$this.user.id"] }
        }
      },
      broadcasterUpvoted: {
        $filter: {
          input: "$votes",
          cond: { $eq: [ "broadcasterUserId", "$$this.user.id"]}
        }
      }
    }
  },
  {
    $project: {
      _id: 1,
      id: 1,
      votesLength: {
        $reduce: {
          input: "$votes",
          initialValue: 0,
          in: {
            $add: [
              "$$value",
              {
                $switch: {
                  branches: [
                    {
                      case: { $eq: ["$$this.voteType","upVote"]},
                      then: 1
                    },
                    {
                      case: { $eq: ["$$this.voteType", "downVote"]},
                      then: -1
                    }
                  ],
                  default: 0
                }
              }
            ]
          }
        }
      },
      broadcasterUpvoted: {
        $arrayElemAt: [
          "$broadcasterUpvoted",
          0
        ]
      },
      hasUpvoted: {
        $arrayElemAt: [
          "$hasUpvoted",
          0
        ]
      }
    }
  }
])

MongoPlayground