MongoDB-使用聚合管道进行评论增减

时间:2020-02-29 21:47:55

标签: javascript database mongodb aggregation-framework

我正在尝试对评论实施upvote / downvote机制(类似于reddit上的upvoting / downvoting机制)。我有一个名为commentReputation的单独集合,里面的文档看起来像这样:

{
    "_id" : ObjectId("5e5acb6d6034a879655c8819"),
    "commentId" : ObjectId("5e5983102328a83d1a4b541f"),
    "creationDate" : ISODate("2020-02-29T20:37:01.509Z"),
    "upvotes" : [
        ObjectId("5e5983102328a83d1a4b53e7"),
        ObjectId("5e5983102328a83d1a4b53e4")
    ],
    "downvotes" : [
       ObjectId("5e5983102328a83d1a4b53e5")
    ]
}

简而言之:每个评论最终都会拥有自己的CommentReputation文档(CommentReputation文档应在有人投票赞成/反对投票时立即创建)

有2种情况:

  1. 该集合为空,这意味着我需要使用给定的commentId CommentReputation创建我的第一个x文档。在项目的其他部分中,我将$setOnInsert{ upsert: true }一起使用,但是(从文档中看)似乎聚合管道目前不支持$setOnInsert。有没有其他方法可以解决这个问题?

  2. 文档在那里,应该进行实际的表决。

    a)upvotesdownvotes数组均不包含试图进行投票的userId,因此无需任何进一步操作即可将其添加到upvotes数组中

    b)upvotes数组包含尝试对注释进行投票的userId,因此应从userId数组中删除upvotes。 (用户已经对此评论进行了投票,并再次单击了“取消投票”按钮,取消了该投票)

    c)downvotes数组包含userId。在这种情况下,应从userId中删除downvotes并将其添加到upvotes

我正在尝试使用updateOne方法和聚集管道来完成上述逻辑,但是我不确定这是否可能。

我目前拥有的是返回"Unrecognized pipeline stage name: '$cond'"

const updateUpvotes = {
  $cond: {
    if: { $elemMatch: { upvotes: ObjectID(userId) } },
    then: { $pull: { upvotes: ObjectID(userId) } },
    else: { $addToSet: { upvotes: ObjectID(userId) } }
  }
};

db.collection(collectionName).updateOne({
   commentId: ObjectID('5e5983102328a83d1a4b541f')
}, [updateUpvotes])

我是否对整个功能有过多的考虑?我想1.问题可以通过简单地创建一个CommentReputation文档(同时创建upvotes文档同时包含空白downvotesComment来解决。

是否有更好的方法?我希望它可以在单个查询请求中运行。也许你们中的某人实现了类似的功能,并且可以给我一些提示。

1 个答案:

答案 0 :(得分:2)

您可以使用以下管道更新来完成此操作,但是它要求upvotes和downvotes数组存在。即使只是空的。

var comment_id = ObjectId("5e5983102328a83d1a4b541f");
var user_id = ObjectId("5e5983102328a83d1a4b53e5");

db.commentReputation.update(
    {
        commentId: comment_id
    },
    [
        {
            $set: {
                upvotes: {
                    $cond: [
                        { $in: [user_id, '$upvotes'] },
                        { $setDifference: ['$upvotes', [user_id]] },
                        { $setUnion: ['$upvotes', [user_id]] }
                    ]
                }
            }
        },
        {
            $set: {
                downvotes: {
                    $cond: [
                        { $in: [user_id, '$downvotes'] },
                        { $setDifference: ['$downvotes', [user_id]] },
                        '$downvotes'
                    ]
                }
            }
        }
    ]
);