热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mongodb的schema设计方法

mongodb的schema设计方法前言mongodb是NoSQL的代表,从使用关系型数据库(MySQL)到使用非关系型数据库(mongodb),其中的一些以前的设计的思维惯性总是

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:
}

原来的设计范式的目标

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

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

  3. 避免数据库访问时的歧义

在mongodb中:

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

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

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

没有约束怎么办?

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

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

没有事务怎么办?

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

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

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

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

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

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

典型的设计场景

一对一的关系

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

一对多的关系

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

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

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

多对多的关系

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

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

树形结构

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

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

嵌入的优势

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

处理大文件

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


推荐阅读
  • php设置数组大小_【大厂必备】2020超经典PHP面试题
    结合我自己这段时间的面试情况,面对的一些php面试题列举出来,基本上结合自己的看法回答的,不妥的地方请大家指出去,与大家一起 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 本文介绍了一个React Native新手在尝试将数据发布到服务器时遇到的问题,以及他的React Native代码和服务器端代码。他使用fetch方法将数据发送到服务器,但无法在服务器端读取/获取发布的数据。 ... [详细]
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
  • MySQL多表数据库操作方法及子查询详解
    本文详细介绍了MySQL数据库的多表操作方法,包括增删改和单表查询,同时还解释了子查询的概念和用法。文章通过示例和步骤说明了如何进行数据的插入、删除和更新操作,以及如何执行单表查询和使用聚合函数进行统计。对于需要对MySQL数据库进行操作的读者来说,本文是一个非常实用的参考资料。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • Opencv提供了几种分类器,例程里通过字符识别来进行说明的1、支持向量机(SVM):给定训练样本,支持向量机建立一个超平面作为决策平面,使得正例和反例之间的隔离边缘被最大化。函数原型:训练原型cv ... [详细]
  • MySQL:互联网公司常用 分库分表
    本文目录一、数据库瓶颈IO瓶颈CPU瓶颈二、分库分表水平分库水平分表垂直分库垂直分表三、分库分表工具四、分库分表步骤五、分库分表问题非partit ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • “你永远都不知道明天和‘公司的意外’哪个先来。”疫情期间,这是我们最战战兢兢的心情。但是显然,有些人体会不了。这份行业数据,让笔者“柠檬” ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
author-avatar
马黛茶总部
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有