在非关系数据库中存储喜欢
Posted
技术标签:
【中文标题】在非关系数据库中存储喜欢【英文标题】:Storing Likes in a Non-Relational Database 【发布时间】:2019-01-13 01:04:47 【问题描述】:要点
我在我的应用程序中实现了一个赞按钮。让我们假设用户能够喜欢其他用户的产品。
问题
我现在想知道以下哪种方法是将这些喜欢存储在非关系数据库(在我的例子中是 MongoDB)中最有效和最可靠的方法。重要的是,没有用户可以两次喜欢一个产品。
可能的解决方案
(1) 将点赞者的用户 ID 存储在产品本身上,并通过likes.length
跟踪点赞数
// Product in database
likes: [
'userId1',
'userId2',
'userId3',
...
],
...
(2) 存储用户自己喜欢的所有产品,并通过产品上的数字跟踪喜欢的数量
// User in database
likedProducts: [
'productId1',
'productId2',
'productId3',
...
]
...
// Product in database
numberOfLikes: 42,
...
(3) 或许有更好的解决方案?
无论哪种方式,如果产品有很多喜欢或用户喜欢很多产品,则需要加载大量数据以显示喜欢并检查用户是否已经喜欢它。
【问题讨论】:
您的解决方案需要支持多少数据?有很多选择,但它们都有取舍,知道您预计会遇到什么限制会非常有帮助。 【参考方案1】:(1) 或 (2) 使用哪种方法取决于您的用例,具体来说,您应该考虑需要更多访问哪些数据:检索特定用户喜欢的所有产品 (2) 或检索所有喜欢特定产品的用户 (1)。看起来更可能的是 (1) 是更常见的情况 - 这样您就可以轻松知道用户是否已经喜欢该产品以及该产品的喜欢数量,因为它只是数组长度。
我认为任何进一步的改进都可能是过早的优化 - 最好针对手头的问题进行优化。
例如,如果显示喜欢的数量似乎是一个瓶颈,您可以通过将数组长度存储为单独的键值来进一步非规范化您的数据。以这种方式显示产品列表不需要从数据库接收带有 userIds 的喜欢数组。
更不可能的是,如果单个产品有数百万个赞,您会发现循环遍历 likes 数组以检查 userId 是否已经在其中会显着减慢。当然,您可以使用sorted array 之类的东西来保持喜欢的排序,但是数据库通信仍然很慢(无论如何都比在内存中循环遍历数组要慢)。最好使用数据库索引进行二分搜索,而不是将喜欢的数组存储为嵌入到产品(或用户)中的数组,您可以将喜欢存储在单独的集合中:
_id: $oid1,
productId: $oid2,
userId: $oid3
假设产品有很多喜欢的键,如果所有 3 个键都被索引,那么这应该是访问喜欢的最快方式。
您也可以发挥创意,使用 $oid2+$oid3 的串联作为 $oid1,这将自动强制用户-产品对喜欢的唯一性。因此,您只需尝试保存它并忽略数据库错误(可能会导致细微的错误,因此在保存失败时检查是否存在会更安全)。
【讨论】:
【参考方案2】:为什么不简单地修改需求并使用关系数据库或类似 RDBMS 的解决方案。基本上,为正确的工作使用正确的工具:
创建另一个表 Likes,将您的 productId 和 userId 对作为唯一键。例如:
userId1 - productId2
userId2 - productId3
userId2 - productId2
userId1 - productId5
userId3 - productId2
然后您可以通过 userId 查询并获取每个用户的点赞数或通过 productId 查询并获取每个产品的点赞数。
而且,唯一键 userId_productId 将保证一个用户只能喜欢一个产品。
此外,您可以在另一列中保留用户喜欢产品时的时间戳等额外信息。
【讨论】:
【参考方案3】:您可能还需要考虑文档大小,在每个产品上存储用户 ID 或在每个用户中存储字符串产品 ID 可能会导致内存中断并且无法很好地扩展。 Rdbms 会更好的解决这个问题。
【讨论】:
以上是关于在非关系数据库中存储喜欢的主要内容,如果未能解决你的问题,请参考以下文章