如何使用 MongoDB 为 "likes" 投票系统建模
How to Model a "likes" voting system with MongoDB
目前我正在开发一款移动应用程序。基本上人们可以 post 他们的照片,追随者可以像 Instagram 一样喜欢这些照片。我使用 mongodb 作为数据库。就像instagram一样,单张照片可能会有很多点赞。所以对单个 "like" 和索引使用文档似乎不太合理,因为它会浪费大量内存。但是,我希望用户快速添加一个赞。所以我的问题是如何为 "like" 建模?基本上数据模型与 instagram 非常相似,但使用 Mongodb.
无论您如何构建整个文档,基本上都需要两件事。这基本上是一个 属性 一个 "count" 和一个 "list" 那些已经 post 编辑了他们的 "like" 以确保没有重复提交的人。这是一个基本结构:
{
"_id": ObjectId("54bb201aa3a0f26f885be2a3")
"photo": "imagename.png",
"likeCount": 0
"likes": []
}
无论如何,您的 "photo post" 和您想要的任何信息都有一个唯一的“_id”,然后是提到的其他字段。这里的 "likes" 属性 是一个数组,它将保存系统中 "user" 对象的唯一“_id”值。所以每个 "user" 在某个地方都有自己的唯一标识符,在本地存储或 OpenId 或其他东西中,但是一个唯一标识符。我将坚持使用 ObjectId
作为示例。
当有人将 "like" 提交到 post 时,您要发出以下更新语句:
db.photos.update(
{
"_id": ObjectId("54bb201aa3a0f26f885be2a3"),
"likes": { "$ne": ObjectId("54bb2244a3a0f26f885be2a4") }
},
{
"$inc": { "likeCount": 1 },
"$push": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") }
}
)
现在 $inc
operation there will increase the value of "likeCount" by the number specified, so increase by 1. The $push
操作将用户的唯一标识符添加到文档中的数组以供将来参考。
这里最重要的事情是记录投票的用户以及声明的 "query" 部分发生的事情。除了通过它自己唯一的“_id”选择要更新的文档外,另一件重要的事情是检查 "likes" 数组以确保当前投票用户不在其中。
反之亦然 "removing" "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
在投影中的这种用法只会 return 当前用户(如果他们存在)或者只是一个空白数组(如果他们不存在)。这允许您的应用程序逻辑的其余部分知道当前用户是否已经投票。
这是基本技术,可能对你有用,但你应该知道嵌入式数组不应该无限扩展,BSON 文档也有 16MB 的硬性限制。所以这个概念是合理的,但如果您期望您的内容有 1000 个 "like votes",则不能单独使用它。有一个称为 "bucketing" 的概念,在此示例中对 Hybrid Schema design 进行了一些详细讨论,它允许一个解决方案存储大量 "likes"。您可以将其与此处的基本概念一起使用,作为批量执行此操作的一种方法。
目前我正在开发一款移动应用程序。基本上人们可以 post 他们的照片,追随者可以像 Instagram 一样喜欢这些照片。我使用 mongodb 作为数据库。就像instagram一样,单张照片可能会有很多点赞。所以对单个 "like" 和索引使用文档似乎不太合理,因为它会浪费大量内存。但是,我希望用户快速添加一个赞。所以我的问题是如何为 "like" 建模?基本上数据模型与 instagram 非常相似,但使用 Mongodb.
无论您如何构建整个文档,基本上都需要两件事。这基本上是一个 属性 一个 "count" 和一个 "list" 那些已经 post 编辑了他们的 "like" 以确保没有重复提交的人。这是一个基本结构:
{
"_id": ObjectId("54bb201aa3a0f26f885be2a3")
"photo": "imagename.png",
"likeCount": 0
"likes": []
}
无论如何,您的 "photo post" 和您想要的任何信息都有一个唯一的“_id”,然后是提到的其他字段。这里的 "likes" 属性 是一个数组,它将保存系统中 "user" 对象的唯一“_id”值。所以每个 "user" 在某个地方都有自己的唯一标识符,在本地存储或 OpenId 或其他东西中,但是一个唯一标识符。我将坚持使用 ObjectId
作为示例。
当有人将 "like" 提交到 post 时,您要发出以下更新语句:
db.photos.update(
{
"_id": ObjectId("54bb201aa3a0f26f885be2a3"),
"likes": { "$ne": ObjectId("54bb2244a3a0f26f885be2a4") }
},
{
"$inc": { "likeCount": 1 },
"$push": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") }
}
)
现在 $inc
operation there will increase the value of "likeCount" by the number specified, so increase by 1. The $push
操作将用户的唯一标识符添加到文档中的数组以供将来参考。
这里最重要的事情是记录投票的用户以及声明的 "query" 部分发生的事情。除了通过它自己唯一的“_id”选择要更新的文档外,另一件重要的事情是检查 "likes" 数组以确保当前投票用户不在其中。
反之亦然 "removing" "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
在投影中的这种用法只会 return 当前用户(如果他们存在)或者只是一个空白数组(如果他们不存在)。这允许您的应用程序逻辑的其余部分知道当前用户是否已经投票。
这是基本技术,可能对你有用,但你应该知道嵌入式数组不应该无限扩展,BSON 文档也有 16MB 的硬性限制。所以这个概念是合理的,但如果您期望您的内容有 1000 个 "like votes",则不能单独使用它。有一个称为 "bucketing" 的概念,在此示例中对 Hybrid Schema design 进行了一些详细讨论,它允许一个解决方案存储大量 "likes"。您可以将其与此处的基本概念一起使用,作为批量执行此操作的一种方法。