mongodb的存储结构是灵活可变的,但是,并不意味着我们就肆意地使用不规则的文档结构。不规则的文档结构对于开发和后期的维护都是一个灾难。所以,还是要有一个约定的格式。

但是,由于前期设计的不周详和其他种种原因,数据库文档结构在开发过程的中修改总是难以避免的,应该尽量减少这种修改。但是,到了必须改的时候还是得改:

  1. {
  2. "_id" : ObjectId("54a1f775e4b03dad3af55c3c"),
  3. "myId" : "54a0b115e4b00712935204ba",
  4. "name" : "action",
  5. "key" : "m_0",
  6. "index" : 0,
  7. "createTime" : ISODate("2014-12-30T00:53:09.483Z"),
  8. "subMs" : [
  9. {
  10. "_id" : null,
  11. "rm" : {
  12. "mt" : "TEXT",
  13. "content" : "撒东西"
  14. },
  15. "name" : "地说道",
  16. "key" : "menu_0_0",
  17. "type" : "CLICK"
  18. }
  19. ]
  20. }
  21. {
  22. "_id" : ObjectId("54b87996e4b04b29b92a71b1"),
  23. "myId" : "54b5e8cce4b045d4121f5d63",
  24. "rm" : {
  25. "msgType" : "URL",
  26. "url" : "http://www.abc.com"
  27. },
  28. "name" : "usercenter",
  29. "key" : "user-center",
  30. "type" : "VIEW",
  31. "index" : 0,
  32. "createTime" : ISODate("2015-01-16T02:38:14.643Z")
  33. }]
  34.  
  35. }

有很多这样类型的文档。 这个文档中的subMs字段中内嵌有若干个文档。要做的事情就是把subMs中的若干个文档脱离出来成为一个独立的文档,并且使新拆出来的文档保留原父文档的id。

脚本如下:

  1. var mList = db.m.find();
  2. var mLength = mList.length;
  3. var mArray = new Array();
  4. // 这一步比较关键,因为find 方法会返回一个游标,
  5. // 如果不先关闭,或者将此游标用完,接下来在继续往
  6. // mongodb中插入数据会导致该游标发生混乱。
  7. // 所以此处未往mongodb中修改前先把游标用完。
  8. while(mList.hasNext()) {
  9. mArray.push(mList.next());
  10. }
  11. for(var i = 0; i < mLength; i ++) {
  12. var mItem = mArray.pop();
  13. var sMList = mItem.subMs;
  14. mItem.subMs = new Array();
  15. if(sMList == 0 || sMList.slength == 0) {
  16. continue;
  17. }
  18. var sMLength = sMList.slength;
  19. for(var j = 0; j < sMLength; j ++) {
  20. var sMItem = sMList.pop();
  21. sMItem.pid = mItem._id.str;
  22. sMItem.index = j;
  23. sMItem.subMs = new Array();
  24. sMItem._id = undefined;
  25. db.m.insert(sMItem);
  26. }
  27. db.m.save(mItem);
  28. }

第一次写起来还是有点吃力,

第一,是由于js的非常不熟悉。翻了好几次w3school才看出了点东西。

第二,是对mongodb查询游标的理解。

着重说说,mongodb 的游标:

游标:在mongodb查询中,返回一个可迭代的对象,这个对象就叫做游标。这个对象保存着所有的查询结果集。

游标的行为:

1. 在mongo shell 中,游标默认显示前20个结果集,敲入 it 翻页。显示下一个 20个。

关闭mongodb 的游标:游标在mongodb中如果没有被迭代到最后,那么它在10分钟后自动关闭。或者是被迭代到最后。

修改mongodb游标的自动过期时间方法为:

var myCursor = db.m.find().addOption(DBQuery.Option.noTimeout);

// DBQuery 这个对象中也有挺多东西,有空翻来看看

由于游标在生存周期中不是隔离的,游标存活期间在对一个文档的写操作可能会时该文档的返回次数超过一次。当这个文档被改变之后,这就是我在写上面脚本的时候一开始缺少了先把游标用完,就对原文档修改,造成错误。

所以,我上面的写法存在问题,当数据量很大的时候,把游标中所有的东西加载到内存后会把内存撑爆的。。。

解决办法:使用游标快照: (P707)

mongodb的游标会对一个文档返回超过一次,在一些特殊的情况下,那么这个时候就可以使用快照方法 snapshot().

snapshot()贯穿在_id字段上的索引,保证查询返回的每个文档出现的_id值不超过一次。(遵循_id值)

快照方法不保证数据返回时会返回单一时刻。 也不保证对插入和删除操作的隔离。

警告:

1.不能再分片集合中使用快照方法

2.不能在快照方法的同时使用 sort方法或者hint()方法。

作为一个选择,如果在集合中存在有一个或多个字段是永远不会改变的,那么可以在该字段上创建唯一索引,来得到和使用库依照方法类似的集合。查询时使用hint方法强制查询时使用这个唯一索引。

第三,mongo shell, 有个好东西, 当敲一个命令的时候,不敲后边跟上的括号,就能显示该命令底下将会执行的js方法。

比如以下命令:

>  db.m.find   回车后会显示对应的方法。

另外,有个挺好用的mongodb客户端:robomongo 值得推荐。

以上参考了mongodb的官方文档。写的很给力的一个文档。非常值得一看,居家备用查询也挺好。

mongodb 修改数据结构的一个例子以及小梳理的更多相关文章

  1. Spark小课堂Week7 从Spark中一个例子看面向对象设计

    Spark小课堂Week7 从Spark中一个例子看面向对象设计 今天我们讨论了个问题,来设计一个Spark中的常用功能. 功能描述:数据源是一切处理的源头,这次要实现下加载数据源的方法load() ...

  2. 一个有趣的小例子,带你入门协程模块-asyncio

    一个有趣的小例子,带你入门协程模块-asyncio 上篇文章写了关于yield from的用法,简单的了解异步模式,[https://www.cnblogs.com/c-x-a/p/10106031. ...

  3. [python]python 遍历一个list 的小例子:

    [python]python 遍历一个list 的小例子: mlist=["aaa","bbb","ccc"]for ss in enume ...

  4. C# 关于委托和事件的妙文:通过一个例子详细介绍委托和事件的作用;Observer模式简介

    委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见 ...

  5. Erlang 程序引发共享内存 bug 的一个例子

    虽然 Erlang 的广告说得非常好,functional.share-nothing.消息传递,blah blah 的,好像用 Erlang 写并发程序就高枕无忧了,但是由于 Erlang 信奉高度 ...

  6. 【C语言探索之旅】 第一部分第八课:第一个C语言小游戏

    ​ 内容简介 1.课程大纲 2.第一部分第八课:第一个C语言小游戏 3.第一部分第九课预告: 函数 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写 ...

  7. 6、GNU makefile工程管理学习的一个例子

    在之前我们已经学习了一个文件的编译过程,但是做过项目的都知道,一个工程中的源文件不计其数,其按类型.功能.模块会分别放在若干个目录中,而这些文件如何编译就需要有一个编译规则,虽然现在很多大型的项目都是 ...

  8. 一个例子理解Predicate、Consumer和Stream

    一个需求: 把年龄大于20的学生的信息打印出来. 面向对象编程 public class Student { private String name; private int age; private ...

  9. 一个例子看懂所有nodejs的官方网络demo

    今天看群里有人用AI技术写了个五子棋,正好用的socket.io,本身我自己很久没看nodejs了,再加上Tcp/IP的知识一直很弱,我就去官网看了下net.socket 发现之前以为懂的一个官方例子 ...

随机推荐

  1. spring项目中使用weblogic的连接池

    1.首先在weblogic控制台中配置好一个数据源 我这里建立的数据源的名称叫 jdbc/app1,JNDI名称也叫 jdbc/app1 2.在spring中配置数据源的时候,做如下配置: <b ...

  2. struts2常用的常量constant

    常用的常量配置  struts.serve.static.browserCache 该属性设置浏览器是否缓存静态内容.当应用处于开发阶段时,我们希望每次请求都获得服务器的最新响应,则可设置该属性为fa ...

  3. maven skip tests

    DskipTests=true is short form of -Dmaven.test.skip=true

  4. 欧拉路径Hrbust1351

    http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1351 这道题先利用并查集的知识点, ...

  5. 剑指Offer:面试题15——链表中倒数第k个结点(java实现)

    问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...

  6. 你很牛B,面试却没过,为什么?

    点击标题下「飞测」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是我们期 ...

  7. 【CImg】三角形绘制算法实现

    这周的CV基础练习是简单的图形绘制:比如说矩形.三角形和圆心什么的.会发现其实矩形和圆形的实现思路都很直白,矩形只需要确认两个对角坐标就可以了,圆心只需要确认圆心和半径,接着就是简单的遍历各个像素点判 ...

  8. Win2D 官方文章系列翻译 - DPI (每英寸点数)和 DIPs(设备独立像素)

    本文为个人博客备份文章,原文地址: http://validvoid.net/win2d-dpi-dips/ 本文旨在解释物理像素与设备独立像素(DIPs, device independent pi ...

  9. uLua Unity工作机制

    基于ulua 1.25版本,开启C#类型动态注册. 一.  步骤 注册需要Wrap的C#类型. 在WrapFile.cs类中,使用_GT(typeof(XXX)), 注册需要Wrap的C#类型 注册的 ...

  10. EXT学习之——Ext下拉框绑定以及级联写法

    /*******步骤有四个,缺一不可*********/ function () {xxxxxx = Ext.extend(construct, {InitControl: function () { ...