gpt4 book ai didi

javascript - 追随者——mongodb 数据库设计

转载 作者:可可西里 更新时间:2023-11-01 02:55:06 26 4
gpt4 key购买 nike

所以我正在使用 mongodb,我不确定我是否有正确/最好的数据库集合设计来完成我正在尝试做的事情。

可以有很多项目,用户可以用这些项目创建新组。任何用户都可以关注任何组!

enter image description here

我不仅将关注者和项目添加到组集合中,因为组中可能有 5 个项目,或者可能有 10000 个(对于关注者也是如此),并且从研究中我认为您不应该使用未绑定(bind)数组(其中限制未知)由于性能问题,当文档由于其扩大的大小而必须移动时。 (无论如何,在遇到性能问题之前,是否有建议的数组长度最大值?)

我认为在以下设计中,一个真正的性能问题可能是当我想要获取用户关注的特定项目的所有组(基于 user_id 和 item_id)时,因为那样我必须找到所有组用户正在关注,并从中找到所有具有 group_id $in 和 item id 的 item_groups。 (但我实际上看不到这样做的任何其他方式)

Follower
.find({ user_id: "54c93d61596b62c316134d2e" })
.exec(function (err, following) {
if (err) {throw err;};

var groups = [];

for(var i = 0; i<following.length; i++) {
groups.push(following[i].group_id)
}

item_groups.find({
'group_id': { $in: groups },
'item_id': '54ca9a2a6508ff7c9ecd7810'
})
.exec(function (err, groups) {
if (err) {throw err;};

res.json(groups);

});

})

有没有更好的数据库模式来处理这种类型的设置?

更新:在下面的评论中添加了示例用例。

任何帮助/建议将不胜感激。

非常感谢,
苹果电脑

最佳答案

我同意其他答案的一般概念,即这是一个边缘关系问题。

MongoDB 数据模型的关键是写入繁重,但这对于这个用例来说可能很棘手,主要是因为如果您想将用户直接链接到项目(更改为一组后跟大量的用户会导致大量写入,您需要一些工作人员来执行此操作)。

让我们研究一下读重模型在这里是否不适用,或者我们是否正在做过早的优化。

重读方法

您主要关注以下用例:

a real performance issue could be when I want to get all of the groups that a user is following for a specific item [...] because then I have to find all of the groups the user is following, and from that find all of the item_groups with the group_id $in and the item id.



让我们来剖析一下:
  • 获取用户关注的所有群组

    这是一个简单的查询:db.followers.find({userId : userId}) .我们将需要 userId 上的索引这将使此操作的运行时间为 O(log n),或者即使对于大 n 也非常快。
  • 从中找到所有具有 group_id $in 的 item_groups和项目ID

    现在这是更棘手的部分。让我们暂时假设项目不太可能成为大量组的一部分。然后是复合索引{ itemId, groupId }效果最好,因为我们可以通过第一个标准显着减少候选集 - 如果一个项目仅在 800 个组中共享并且用户关注 220 个组,那么 mongodb 只需要找到这些的交集,这相对容易,因为两者套装很小。

  • 不过,我们需要比这更深入:

    您的数据结构可能是 的结构复杂网络 .复杂网络有多种形式,但假设您的关注者图是 nearly scale-free 是有道理的。 ,这也几乎是最坏的情况。在无标度网络中,极少数节点(名人、 super 碗、维基百科)吸引了大量“注意力”(即有很多连接),而大量节点难以获得相同数量的注意力结合。

    小节点不用担心 ,上述查询,包括到数据库的往返,都在 中。 2ms 范围 在我的开发机器上的数据集上有数千万个连接和 > 5GB 的数据。现在数据集并不大,但无论你选择什么技术,都会受到 RAM 限制,因为索引无论如何都必须在 RAM 中(数据在网络中的局部性和可分离性通常很差),并且集合的交集大小为根据定义小。换句话说:这个体制主要是硬件瓶颈。

    呢? super 节点尽管?

    由于这只是猜测,而且我对网络模型很感兴趣,我 took the liberty of implementing a dramatically simplified network tool根据您的数据模型进行一些测量。 (抱歉,它是用 C# 编写的,但是用我最熟悉的语言来生成结构良好的网络已经够难的了……)。

    查询 super 节点时,我得到的结果范围是 7ms 最高 (这是在 1.3GB db 中的 12M 条目上, 最大组中包含 133,000 个项目 和一个用户跟随 143 个组。)

    假设 在这段代码中,用户跟随的组数并不大,但这在这里似乎是合理的。如果不是,我会选择大量写入的方法。

    随意使用代码。不幸的是,如果你想用超过几 GB 的数据来尝试这个,它需要一些优化,因为它根本没有优化并且在这里和那里做了一些非常低效的计算(特别是 beta 加权随机洗牌可以改进)。

    换句话说:我还不会担心重读方法的性能。 问题通常不在于用户数量的增长,而在于用户以意想不到的方式使用系统。

    写重方法

    另一种方法可能是颠倒链接顺序:
    UserItemLinker
    {
    userId,
    itemId,
    groupIds[] // for faster retrieval of the linker. It's unlikely that this grows large
    }

    这可能是最具扩展性的数据模型,但除非我们讨论大量数据,其中分片是关键要求,否则我不会选择它。这里的关键区别在于,我们现在可以通过使用 userId 作为分片键的一部分来有效地划分数据。这有助于在多数据中心场景中并行化查询、有效分片和改善数据局部性。

    这可以使用更复杂的测试平台进行测试,但我还没有找到时间,坦率地说,我认为这对大多数应用程序来说太过分了。

    关于javascript - 追随者——mongodb 数据库设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28421505/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com