如何用MongoDBbuild立“喜欢”投票系统

目前我正在开发一个移动应用程序。 基本上人们可以张贴他们的照片和追随者可以像Instagram的照片。 我使用mongodb作为数据库。 像Instagram一样,可能会有很多喜欢单张照片。 所以使用一个索引单个“像”的文件似乎是不合理的,因为它会浪费大量的内存。 不过,我想要一个用户快速添加一个。 所以我的问题是如何build模“喜欢”? 基本上数据模型是非常类似于instagram,但使用Mongodb。

不pipe你如何构build你的整体文档,基本上有两件事情是你需要的。 这基本上是一个属性四,已经在那里“贴”的人的“数”和“名单”,以确保没有重复提交。 这是一个基本的结构:

 { "_id": ObjectId("54bb201aa3a0f26f885be2a3") "photo": "imagename.png", "likeCount": 0 "likes": [] } 

无论如何,有一个独特的“_id”为你的“照片岗位”,无论你想要的信息,但其他领域提到。 这里的“likes”属性是一个数组,并且将保存来自系统中“用户”对象的唯一“_id”值。 所以每个“用户”都有自己的唯一标识符,无论是在本地存储或OpenId或其他东西,而是一个唯一的标识符。 我将坚持使用ObjectId作为例子。

当有人提交一个“喜欢”的post,你想发出以下更新声明:

 db.photos.update( { "_id": ObjectId("54bb201aa3a0f26f885be2a3"), "likes": { "$ne": ObjectId("54bb2244a3a0f26f885be2a4") } }, { "$inc": { "likeCount": 1 }, "$push": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") } } ) 

现在$inc操作将会增加指定数字“likeCount”的值,所以增加1. $push操作将用户的唯一标识符添加到文档中的数组中以供将来参考。

这里主要的重点是logging那些投票的用户以及发言中“查询”部分发生的事情。 除了通过自己独特的“_id”select文件来更新,另一个重要的是检查“likes”数组,以确保当前的投票用户不在那里。

对于相反的情况也是如此,或者“去除”“喜欢”:

 db.photos.update( { "_id": ObjectId("54bb201aa3a0f26f885be2a3"), "likes": ObjectId("54bb2244a3a0f26f885be2a4") }, { "$inc": { "likeCount": -1 }, "$pull": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") } } ) 

这里最主要的是用查询条件来确保在所有条件都不符合的情况下没有文件被触及。 因此,如果用户在更新时已经投票或者减less了投票,那么计数不会增加。

当然,在应用程序的任何其他部分读取一个数组中有几百个条目的数组是不现实的。 但是MongoDB也有一个非常标准的方法来处理这个问题:

 db.photos.find( { "_id": ObjectId("54bb201aa3a0f26f885be2a3"), }, { "photo": 1 "likeCount": 1, "likes": { "$elemMatch": { "$eq": ObjectId("54bb2244a3a0f26f885be2a4") } } } ) 

在投影中$elemMatch这种用法只会返回当前用户,如果他们存在或只是一个空白的数组,他们不是。 如果当前用户已经投票或不投票,这可以让您的其他应用程序逻辑知道。

这是基本的技术,可以按原样工作,但是您应该意识到embedded式数组不应该无限扩展,并且对BSON文档也有16MB的限制。 所以这个概念是有道理的,但是如果你期望在你的内容上有1000个“赞成票”,就不能单独使用它。 有一个被称为“bucketing”的概念,在这个混合模式devise的例子中有详细的讨论,它允许一个解决scheme来存储大量的“喜欢”。 你可以看看在这里使用的基本概念作为一个方法来做到这一点的数量。