jjzjj

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

coder 2024-05-18 原文

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

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



我不仅将关注者和项目添加到组集合中,因为组中可能有 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/

    有关javascript - 追随者——mongodb 数据库设计的更多相关文章

    1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

      我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

    2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    3. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

      我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

    4. ruby - Ruby 有 `Pair` 数据类型吗? - 2

      有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

    5. ruby - 我如何添加二进制数据来遏制 POST - 2

      我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

    6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

      无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

    7. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

      本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

    8. 使用canal同步MySQL数据到ES - 2

      文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

    9. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

      我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

    10. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

      文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

    随机推荐