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

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

 {
"_id" : ObjectId("54a1f775e4b03dad3af55c3c"),
"myId" : "54a0b115e4b00712935204ba",
"name" : "action",
"key" : "m_0",
"index" : 0,
"createTime" : ISODate("2014-12-30T00:53:09.483Z"),
"subMs" : [
{
"_id" : null,
"rm" : {
"mt" : "TEXT",
"content" : "撒东西"
},
"name" : "地说道",
"key" : "menu_0_0",
"type" : "CLICK"
}
]
}
{
"_id" : ObjectId("54b87996e4b04b29b92a71b1"),
"myId" : "54b5e8cce4b045d4121f5d63",
"rm" : {
"msgType" : "URL",
"url" : "http://www.abc.com"
},
"name" : "usercenter",
"key" : "user-center",
"type" : "VIEW",
"index" : 0,
"createTime" : ISODate("2015-01-16T02:38:14.643Z")
}] }

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

脚本如下:

 var mList = db.m.find();
var mLength = mList.length;
var mArray = new Array();
// 这一步比较关键,因为find 方法会返回一个游标,
// 如果不先关闭,或者将此游标用完,接下来在继续往
// mongodb中插入数据会导致该游标发生混乱。
// 所以此处未往mongodb中修改前先把游标用完。
while(mList.hasNext()) {
mArray.push(mList.next());
}
for(var i = 0; i < mLength; i ++) {
var mItem = mArray.pop();
var sMList = mItem.subMs;
mItem.subMs = new Array();
if(sMList == 0 || sMList.slength == 0) {
continue;
}
var sMLength = sMList.slength;
for(var j = 0; j < sMLength; j ++) {
var sMItem = sMList.pop();
sMItem.pid = mItem._id.str;
sMItem.index = j;
sMItem.subMs = new Array();
sMItem._id = undefined;
db.m.insert(sMItem);
}
db.m.save(mItem);
}

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

第一,是由于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. MS SQL SERVER 数据库日志压缩方法与代码

    MS SQL性能是很不错的,但是数据库用了一段时间之后,数据库却变得很大,实际的数据量不大.一般都是数据库日志引起的!数据库日志的增长可以达到好几百M. DUMP TRANSACTION [数据库名] ...

  2. maven配置开发

    1.项目中使用Log4j对其日志进行配置管理,采取的方式一种是通过properties文件设置,另一种方式就是通过设置xml文件的配置. 使用场景: 编程模型:log.err();log.debug( ...

  3. 剑指Offer:面试题17——合并两个排序的链表

    题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 思路1: 分别用p1,p2两个指针扫描两个有序链表,p3指针去构建新链表h3. p1.val & ...

  4. 技术转载:Jni学习四:如何编写jni方法

    转载:http://blog.chinaunix.net/u1/38994/showart_1099528.html 一.概述: 在这篇文章中将会简单介绍如何编制一些简单的JNI 方法.我们都知道JN ...

  5. Redis主从是否生效的特殊测试方法

    Redis主从的特殊测试方法 配置主从 Redis的主从设定,相较于MySQL的主从,配置起来非常简单,不必像MySQL数据库一样手动记录bin log的位置再配置,但又可以像MySQL一样,一主带多 ...

  6. Spring Cloud 开门见山

    Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,为开发者提供了在分布式系统(配置管理,服务发现,熔断,路由,微代理,控制总线,一次性toke ...

  7. 【练习】显示MySQLadmin 库户籍选项

    [oracle@enmo ~]$ mysqladmin -V mysqladmin Ver , for Linux on x86_64

  8. oracle创建job权限

    grant create job to ja_ods; grant manage scheduler to ja_ods;

  9. js实现简单的滑动门和tab选项卡

    思想:首先定义三个选项卡,可以用任何标签,只要如下图, 一共有三个ul,第一个ul给一个class,因为默认第一个选项卡的内容显示出来, 其他两个ul  display:none: 当我鼠标移到第二个 ...

  10. leetcode 9

    判断一个数是否为回文数,不利用额外的空间. 思路:将数反转后进行比较. 注意:反转之后数越界的判断,若越界,则不是回文数:负数不是回文数: 代码如下: class Solution { public: ...