如果不存在则插入,否则删除MongoDB [英] Insert if not exists, else remove MongoDB

查看:95
本文介绍了如果不存在则插入,否则删除MongoDB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我在MongoDB(2.6.4)中有一个查询,试图在其中实现简单的upvote/downvote机制.当用户单击upvote时,我需要执行以下操作:

So I have a query in MongoDB (2.6.4) where I am trying to implement a simple upvote/downvote mechanism. When a user clicks upvote, I need to do the following:

如果已被用户投票,则删除投票.

If already upvoted by user, then remove upvote.

否则,如果用户未批准,则添加upvote并删除downvote(如果存在).

Else if not upvoted by user, then add upvote AND remove downvote if exists.

到目前为止,我形成的查询(不正确)是:

So far, my query formed (is incorrect) is:

db.collection.aggregate([
{
    $project: {
        "_id" : ObjectId("53e4d45c198d7811248cefca"),
        "upvote": {
           "$cond": 
            [
            {"$in": ["$upvote",1] },
            {"$pull": {"upvote" : 1}},
            {"$addToSet": {"upvote" : 1}, "$pull": {"downvote": 1}}
            ]
        }
    }
}
])

其中"1"是尝试进行投票的用户ID. upvotedownvote都是分别包含已投票和已投票的用户ID的数组.

where '1' is the user id who is trying to upvote. Both upvote and downvote are arrays that contain userIds of those who have upvoted and downvoted, respectively.

对于查询的输出,我只想要一个布尔值:true如果$cond评估为true,否则为false.

For output of query, I just want a bool value: true if $cond evaluated to true, else false.

推荐答案

这不是实施上投票和下投票的好方法.除了聚合框架不是以任何方式更新文档的机制之外,由于要实现的逻辑,您似乎倾向于认为它可能是一种解决方案.但是聚合不会更新.

That's not a good way to implement up-votes and downvotes. Aside from the aggregation framework not being a mechanism for updating documents in any way, you seem to have gravitated towards thinking it may be a solution due to the logic you want to implement. But aggregate does not update.

您想要的东西,让我们称其为问题"模式是这样的结构:

What you want on your, well lets call it a "question" schema is a structure like this:

{
    "_id": ObjectId("53f51a844ffa9b02cf01c074"),
    "upvoted": [],
    "downvoted": [],
    "upvoteCount": 0,
    "downvoteCount": 0
}

这可以很好地与原子更新一起使用,并且实际上可以同时为您提供有关该对象的一些状态信息.

That is something that can work well with atomic updates and actually give you some stateful information about the object at the same time.

对于"upvoted"和"downvoted"数组,我们将考虑"users"投票具有相似的唯一ObjectId值.因此,我们要做的是 $push $pull 从任一数组开始,并同时将计数器值以及这些操作中的每一个递增/递减".

For the "upvoted" and "downvoted" arrays, we are going to consider that the "users" voting have a similar unique ObjectId value. So what we are going to do is $push or $pull from either array and also "increment/decrement" the counter values along with each of those operations.

这是投票的工作方式:

db.questions.update(
    { 
        "_id": ObjectId("53f51a844ffa9b02cf01c074"),
        "upvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
        "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075")
    },
    {         
        "$push": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
        "$inc": { "upvoteCount": 1, "downvoteCount": -1 },
        "$pull": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
    }
)

db.questions.update(
    { 
        "_id": ObjectId("53f51a844ffa9b02cf01c074"),
        "upvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
    },
    {
        "$push": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
        "$inc": { "upvoteCount": 1 },
    }
)

实际上这是两个操作,您可以使用批量操作AP 我也是(这也许是最好的方法),但它有一点意义.第一条语句仅与当前用户在数组中记录了"downvote"的文档匹配.这样,我们已经将该用户ID值推"到"downvotes"数组中.如果不存在,则不进行任何更新.但是,您既要从各自的数组中进行推拉操作,又要同时递增/递减"计数器字段.

Actually that's two operations, which you could do with the Bulk operations API as well (probably the best way really) but it has a point to it. The first statement will only match a document where the current user has a "downvote" recorded in the array. As it, we already "pushed" that user id value to the "downvotes" array. If it is not there then no update is made. But you both push and pull from respective arrays and also "increment/decrement" the counter fields at the same time.

使用第二条语句仅匹配第一个语句所不匹配的内容,您进行了公平的评估,现在您无需触摸"downvotes",只需处理upvote字段即可.在这两种情况下,安全的做法是确保主要条件是"upvoted"数组中不存在当前用户ID值.

With the second statement which will only match something where the first did not, you make a fair assessment that now you don't need to touch "downvotes" and just handle the upvote fields. In both cases the safe thing to do is make sure that the main condition is the current user id value is not present in the "upvoted" array.

对于向下投票,这些字段将被颠倒:

For downvotes the fields are just reversed:

db.questions.update(
    { 
        "_id": ObjectId("53f51a844ffa9b02cf01c074"),
        "downvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
        "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075")
    },
    {         
        "$pull": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
        "$inc": { "upvoteCount": -1, "downvoteCount": 1 },
        "$push": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
    }
)

db.questions.update(
    { 
        "_id": ObjectId("53f51a844ffa9b02cf01c074"),
        "downvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
    },
    {
        "$push": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
        "$inc": { "downvoteCount": 1 },
    }
)

自然地,您可以看到为所涉及的用户简单地取消任何"upvote/downvote"的逻辑过程.另外,如果您愿意并且可以在客户端中公开信息,以显示当前用户是否已经投票赞成/拒绝投票",还可以控制点击操作并消除不必要的请求,那么您就可以对此有所了解.

Naturally you can see the logical progression to simply cancelling any "upvote/downvote" for the user in question. Also you can be smart about it if you want and expose the information in your client to not only show if the current user have already "upvoted/downvoted" but also control click actions and eliminate unnecessary requests.

这篇关于如果不存在则插入,否则删除MongoDB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆