资讯专栏INFORMATION COLUMN

mongodb 的 schema 设计方法

jay_tian / 3193人阅读

摘要:下面就来总结一些设计的原则和方法。在城市信息嵌入在人中就更不合适了,因为还会产生大量数据冗余,更新信息也特别麻烦。另一个做法就是嵌在一起,这样会有性能的提升,不过这种做法会导致数据冗余,看具体的情况来取舍。

mongodb 的schema设计方法 前言

mongodb是NoSQL的代表,从使用关系型数据库(MySQL)到使用非关系型数据库(mongodb),其中的一些以前的设计的思维惯性总是在不知不觉的影响着自己的决策。设计的思想有共同之处,也有很大的不同。mongodb的优势在于他表示数据的方式非常丰富。下面就来总结一些设计的原则和方法。

原则

schema的设计最重要的不是当前设计的可扩展性,对设计的可读性,还是说原来的设计三范式。最重要的在于,你的app一般展现出来的数据是什么结构,就设计成什么样。取出即用。举个例子来说,如果设计一个博客的schema,按照原来的方法, 你可能会设计成:

posts
{
  _id: ,
  title: ,
  body: ,
  author: ,
  date: 
}

comments
{
  _id: ,
  post_id: ,
  author: ,
  order: 
}

tags
{
  _id: ,
  tag: ,
  post_id:
}

但是更好的设计是:

{
  _id: ,
  author: ,
  body: ,
  comments : [
    {
      body: ,
      email: ,
      author: ,
    },
    ...
    {
     ...
    }
  ],
  date: ,
  tags: [
    ...
  ],
  title: 
}

原来的设计范式的目标

尽可能的减少数据库数据修改的难度(减少数据冗余)

最小化数据库设计扩展的改动

避免数据库访问时的歧义

在mongodb中:

默认的来说设计的时候是要避免数据冗余的

不存在这样的问题,因为mongo中的schema非常灵活,你可以随时的改动

由于设计的时候就尽可能的按照应用需要的数据的形式设计,取出即用,所以第三个问题出现的概率也比较少

没有约束怎么办?

在mongo中,最经常思考的问题就是,没有外键怎么保持数据一致性?正如上述博客的第一种设计中,你在新插入一个评论的时候,数据库是不会保证你这个post_id是不是真在在posts这个collection里面有对应值。

解决的办法就是像第二种设计中的做法,把他嵌入在posts这个collection.由于这个时候评论已经是post的一部分,就再也不用担心插入的评论没有对应到一篇博客的问题。

没有事务怎么办?

在目前,mongodb是不支持事务的。也就是说,如果你一个业务需要修改好几条记录,你是没办法保证当其中一个操作失败的以后将其它操作回滚的,这种时候又应该怎么办?

虽然mongo没有提供事务,但是他提供了非常丰富的原子操作,我们应该充分利用这一点。在关系型数据库中,你可能有几张表,然后要通过join的方式去链接。所以你需要事务去同时修改几张表。但是在mongo中,在设计的时候你已经prejoin了(就是你已经把它们都嵌入在了同一个collection),你只需要直接一次修改整个post就可以实现事务的效果。

总的来说,解决的办法有三个:

重建你的设计,使得你能通过原子操作一次把它们都修改完

在你的软件中实现锁的机制,用寻找和修改写一系列的测试来实现。

在大量的数据或者不严格的场景中,容忍这种错误

典型的设计场景 一对一的关系

比如说应聘者和简历的关系。除非嵌在一起会导致你的数据大于16MB(mongo的限制),你都应该嵌在一起。做好的做法就是将一个比较少使用的嵌入一个经常食用的当中。

一对多的关系

比如说城市和人的关系,博客和评论

对于像城市和人的关系这样的,一个城市实在是对应了太多太多的人。如果将人嵌入在城市中,不太合适。在城市信息嵌入在人中就更不合适了,因为还会产生大量数据冗余,更新信息也特别麻烦。这种情况下最好的做法就是分开两个collection,然后人的collection中每一条都有一个city字段,来对应城市collection中的一条。

如果是像博客和评论这样一个对应的不是特别多的时候,最好的最法还是嵌进去

多对多的关系

例如书和作者的关系,老师和学生的对应关系

对于像书和作者这样,比较少对应比较少的,一个可行的做法就是分开两个collection。书collection中存一个authors数组,作者 collection中存一个books数组,互相对应。这种做法不好的地方就在与要手动维护数据一致性。另一个做法就是嵌在一起,这样会有性能的提升,不过这种做法会导致数据冗余,看具体的情况来取舍。特别的像老师和学生这种关系,最好最好就是不要将老师嵌在学生中,因为很可能一个新来的老师就还没有学生,这样你就没办法把这位老师加入到系统中。

树形结构

一个典型的场景就是像amazon这样的电商,一个商品分类下可能有很多个子分类。

其中的一个做法就是建立一个分类的collection,然后每个分类有一个parent_id字段,但是这样不便于找到他所有的祖先。所以比较好的做法是再加一个ancesters的数组字段,记录他所有的祖先的id,这样就能方便的查询到他的祖先和后代。

嵌入的优势

提高读的效率。这意味着你要获取数据只需要查询一次数据库就行了。

处理大文件

如果一个数据量特别大(大于16M),比如读入一个100多M的mp4文件。这种情况下就需要用到GRIDFS.原理就是把他分割成一个一个小的块

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/18868.html

相关文章

  • vue2.0开发聊天程序(六) 搞定mongodb

    摘要:为安装文件,无需再配置环境变量。连接操作有以下包作者并未查到除此之外的包,但不代表没有。等于是每个默认配置的主键属性,属性名为可自己定义一个来覆盖此属性。需要注意的是,在新版本的文档中,为。通过创建限于篇幅,本小节暂时写到这里。 我的琴声呜咽,我的泪水全无。我把远方的远归还草原。                   - 海子《九月》 mongodb安装 什么是Mongodb?就是一个基...

    Dr_Noooo 评论0 收藏0
  • 在Node中基于Mongoose对MongoDB进行增删查改(CRUD)操作(一)

    摘要:如图连接成功后,显示你的数据库,在这个节目可以对数据库进行操作。如图安装与加载首先假定你已经安装了,命令行工具输入在使用的文件中即可。创建读取更新删除单值读取上文是在中基于对进行增删查改操作的简单介绍,以后会有进阶的文章。 关键词:mongodb安装 mongoose使用 robomongo mongoose的CRUD操作 mongoose的查询,增加,修改,删除 工具介绍 Mon...

    lemon 评论0 收藏0
  • 在Node中基于Mongoose对MongoDB进行增删查改(CRUD)操作(一)

    摘要:如图连接成功后,显示你的数据库,在这个节目可以对数据库进行操作。如图安装与加载首先假定你已经安装了,命令行工具输入在使用的文件中即可。创建读取更新删除单值读取上文是在中基于对进行增删查改操作的简单介绍,以后会有进阶的文章。 关键词:mongodb安装 mongoose使用 robomongo mongoose的CRUD操作 mongoose的查询,增加,修改,删除 工具介绍 Mon...

    SillyMonkey 评论0 收藏0
  • 一个基于Vue.js+Mongodb+Node.js博客内容管理系统

    摘要:三更新内容在原来项目的基础上,做了如下更新数据库重新设计,改成以用户分组的数据库结构应数据库改动,所有接口重新设计,并统一采用和网易立马理财一致的接口风格删除原来游客模式,增加登录注册功能,支持弹窗登录。 这个项目最初其实是fork别人的项目。当初想接触下mongodb数据库,找个例子学习下,后来改着改着就面目全非了。后台和数据库重构,前端增加了登录注册功能,仅保留了博客设置页面,但是...

    wh469012917 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<