首页 > 解决方案 > 在非关系数据库中存储喜欢

问题描述

要旨

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

问题

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

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

标签: databasemongodbmongoosenosqlnon-relational-database

解决方案


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

我会争辩说,任何进一步的改进都可能是过早的优化——最好用手头的问题进行优化。

例如,如果显示喜欢的数量似乎是一个瓶颈,您可以通过将数组长度存储为单独的键值来进一步非规范化数据。以这种方式显示产品列表不需要从数据库接收带有 userIds 的喜欢数组。

更不可能的是,如果单个产品有数百万个赞,您会发现循环遍历 likes 数组以检查 userId 是否已经在其中会显着减慢。当然,您可以使用排序数组之类的东西来保持喜欢的排序,但是数据库通信仍然很慢(无论如何都比在内存中循环遍历数组要慢)。最好使用数据库索引进行二分搜索,而不是将喜欢的数组存储为嵌入到产品(或用户)中的数组,您可以将喜欢存储在单独的集合中:

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

假设该产品具有许多喜欢的键,如果所有 3 个键都被索引,那么这应该是访问喜欢的最快方式。

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


推荐阅读