目前我正在开发一款移动应用程序.基本上,人们可以发布自己的照片,粉丝们也可以喜欢Instagram这样的照片.我使用mongodb作为数据库.像instagram一样,一张照片可能会有很多人喜欢.因此,将文档用于带有索引的单个"like"似乎不合理,因为这将浪费大量内存.但是,我希望用户快速添加一个like.所以我的问题是如何模拟"like"?基本上,数据模型与instagram非常相似,但使用的是Mongodb.

推荐答案

无论你如何构建你的整体文档,基本上你需要两件事.这基本上是一个"计数"和"名单"的财产,这些人已经发布了他们的"喜欢",以确保没有重复提交.以下是一个基本 struct :

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

不管是哪种情况,你的"照片帖子"和你想要的任何信息都有一个唯一的"_id",但其他字段也一样.这里的"likes"属性是一个数组,它将保存系统中"user"对象的唯一"_id"值.所以每个"用户"在某个地方都有自己的唯一标识符,无论是在本地存储中还是在OpenId中,但都是唯一的标识符.以ObjectId为例.

当有人向帖子提交"赞"时,您需要发出以下更新声明:

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

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

这里最重要的是记录那些投票的用户,以及在声明的"查询"部分发生了什么.除了通过文档自身唯一的"_id" Select 要更新的文档外,另一件重要的事情是判断"likes"数组,以确保当前投票用户不在其中.

反之亦然,或"删除"了"like":

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

这里最重要的是使用查询条件,以确保在不满足所有条件的情况下不会触碰任何文档.因此,如果用户已经投票,计数不会增加,如果更新时他们的投票不再实际存在,计数也不会减少.

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

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

在投影中使用$elemMatch只会返回当前用户,如果他们存在,或者只是一个空白数组,而他们不存在.这允许应用程序逻辑的其余部分知道当前用户是否已经进行了投票.

这是最基本的技术,可能对您很有用,但您应该知道,嵌入式数组不应该无限扩展,BSON文档也有16MB的硬限制.因此,这个概念是合理的,但如果你希望在你的内容上获得Hybrid Schema design0张"赞成票",就不能单独使用.有一个称为"bucketing"的概念,在本例中对其进行了详细讨论,该概念允许一个解决方案存储大量的"like".你可以把它和这里的基本概念一起作为一种批量操作的方法.

Mongodb相关问答推荐

根据参考图计算子文档列表的最大值

Mongo 聚合查找 $gte 6 个月前的日期,以DD-MM-YYYY格式存储为字符串

如何在 MongoDB 中的集合下查找同一文档

MongoDB 聚合 - $project 和 $match 阶段未按预期工作

Mongoose updateMany 以及 Where 和 orWhere?

将子文档中的所有字段设置为 false,然后在单个查询中将第二个字段设置为 true

当属性确实存在时,为什么mongoose模型的 hasOwnProperty 返回 false?

是否可以迭代 mongo 游标两次?

如何在 MongoDB 中存储时间?作为字符串?给出任意年/月/日?

使用 ObjectId.GenerateNewId() 还是离开 MongoDB 创建一个?

Mongoose:填充填充字段

ExpressJS & Mongoose REST API struct :最佳实践?

mongodb-nodejs-driver,DeprecationWarning:collection.count 已弃用

MongoDB count() 未定义

majority和 linearizable的区别

在 mongodb 中的索引列上查找重复项的快速方法

如何使用 MongoDB C# 驱动程序有条件地组合过滤器?

try 启用 Mongo DB 身份验证时发生 TypeError

如何向 mongodb 2.6 添加身份验证?

Mongodb同时在多个字段上聚合(计数)