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. [Flex] ButtonBar系列——控制ButtonBar菜单是否可用

    <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="ht ...

  2. shell local

    Shell函数定义的变量默认是global的,其作用域从"函数被调用时执行变量定义的地方"开始,到shell结束 http://blog.chinaunix.net/xmlrpc. ...

  3. spring错误<context:property-placeholder>:Could not resolve placeholder XXX in string value XXX

    spring同时集成redis和mongodb时遇到多个资源文件加载的问题 这两天平台中集成redis和mongodb遇到一个问题 单独集成redis和单独集成mongodb时都可以正常启动程序,但是 ...

  4. android github

    Action Bars ActionBarSherlock Extended ActionBar FadingActionBar GlassActionBar v7 appcompat library ...

  5. (medium)LeetCode 222.Count Complete Tree Nodes

    Given a complete binary tree, count the number of nodes. Definition of a complete binary tree from W ...

  6. (转)C# SSL-X509使用

    X.509 给出的鉴别框架是一种基于公开密钥体制的鉴别业务密钥管理.一个用户有两把密钥:一把是用户的专用密钥(简称为:私钥),另一把是其他用户都可得到和利用的公共密钥(简称为:公钥).该鉴别框架允许用 ...

  7. PHP过滤HTML标签的三种方法

    在做项目的过程中,我们经常需要用到过滤一些html标签来实现提高数据的安全性,其实就是删除那些对应用程序有潜在危害的数据.它用于去除标签以及删除或编码不需要的字符.首先分享一些比较常见的 $str=p ...

  8. HDU 4771 Stealing Harry Potter's Precious

    Stealing Harry Potter's Precious Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  9. 2014年值得学习的25个PS CS6教程(一)

    热爱PS的朋友看过来~~~下面跟大家推荐10个高端大气上档次的PS教程(都是英文的哦) 1.为4D电影创建一副3D海报 2.制作3D水果文字 3.肖像图混合数字工艺 4.‘Doctrich – Pos ...

  10. flex经验记录(转载)

    最近一直忙于项目,很好抽出时间学习,刚忙里偷闲浏览博客看到一位博友总结的一些flex的经验,感觉不错就转载过来,一来扩散一下,二来保存下来,以后忘记的时候可以回来学习下. 原博文地址:http://b ...