在非关系数据库中存储喜欢

时间:2018-08-06 06:03:22

标签: database mongodb mongoose nosql non-relational-database

要旨

我在应用程序中实现了一个赞按钮。假设用户能够喜欢其他用户的产品。

问题

我现在想知道以下哪种方法是将那些喜欢存储在非关系数据库(在我的情况下为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)也许对此有更好的解决方案?

无论哪种方式,如果产品有很多喜欢或用户喜欢许多产品,则有大量数据需要加载以显示喜欢并检查用户是否已经喜欢。

3 个答案:

答案 0 :(得分:3)

为什么干脆不修改要求,而使用关系数据库或RDBMS相似的解决方案。基本上,使用正确的工具完成正确的工作:

创建另一个表Like,该表将您的productId和userId对保留为唯一键。例如:

userId1 - productId2
userId2 - productId3
userId2 - productId2
userId1 - productId5
userId3 - productId2

然后,您可以按userId查询并获得每个用户的点赞次数,也可以按productId查询并获得每个产品的点赞次数。

此外,唯一键userId_productId将确保一个用户只能喜欢一种产品。

此外,您可以在其他列中保留用户喜欢该产品时的其他信息,例如时间戳记。

答案 1 :(得分:1)

哪种使用方法(1)或(2)取决于您的用例,具体地说,您应该考虑需要使用哪些数据来访问更多数据:检索特定用户喜欢的所有产品(2)或检索所有喜欢特定产品的用户(1)。 (1)很可能是一种更常见的情况-这样一来,您可以轻松地知道用户是否已经喜欢该产品以及该产品的喜欢次数,因为它只是数组长度。

我认为任何进一步的改进都可能是过早的优化-最好解决手头的问题。

例如,如果显示喜欢数似乎是瓶颈,则可以通过将数组长度存储为单独的键值来进一步规范化数据。这样,显示产品列表将不需要从数据库接收带有用户ID的点赞阵列。

更不可能的是,单个产品有数百万个赞,您发现遍历Likes数组以检查userId是否已包含在其中的速度大大降低。当然,您可以使用类似sorted array的东西来保持喜欢的排序,但是数据库通信仍然很慢(比循环遍历内存中的数组要慢)。最好使用数据库索引进行二进制搜索,而不是将喜欢的数组存储为产品(或用户)中嵌入的数组,而可以将喜欢的数组存储在单独的集合中:

{
    _id: $oid1,
    productId: $oid2,
    userId: $oid3
}

假设产品具有带有多个点赞的键,那么如果所有3个键都已索引,则应该是访问点赞的最快方法。

您也可以发挥创造力,并使用$ oid2 + $ oid3的串联作为$ oid1,这将自动强制用户-产品对喜欢的唯一性。因此,您只需尝试保存它,然后忽略数据库错误(可能会导致细微的错误,因此在保存失败时检查是否存在会更安全)。

答案 2 :(得分:-1)

您可能还需要考虑文档的大小,在每个产品上存储用户ID或在每个用户中存储字符串产品ID可能会导致内存不足,并且扩展性不会很好。 Rdbms将是解决此问题的更好方法。