mongodb 修改数据结构的一个例子以及小梳理
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 修改数据结构的一个例子以及小梳理的更多相关文章
- Spark小课堂Week7 从Spark中一个例子看面向对象设计
Spark小课堂Week7 从Spark中一个例子看面向对象设计 今天我们讨论了个问题,来设计一个Spark中的常用功能. 功能描述:数据源是一切处理的源头,这次要实现下加载数据源的方法load() ...
- 一个有趣的小例子,带你入门协程模块-asyncio
一个有趣的小例子,带你入门协程模块-asyncio 上篇文章写了关于yield from的用法,简单的了解异步模式,[https://www.cnblogs.com/c-x-a/p/10106031. ...
- [python]python 遍历一个list 的小例子:
[python]python 遍历一个list 的小例子: mlist=["aaa","bbb","ccc"]for ss in enume ...
- C# 关于委托和事件的妙文:通过一个例子详细介绍委托和事件的作用;Observer模式简介
委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见 ...
- Erlang 程序引发共享内存 bug 的一个例子
虽然 Erlang 的广告说得非常好,functional.share-nothing.消息传递,blah blah 的,好像用 Erlang 写并发程序就高枕无忧了,但是由于 Erlang 信奉高度 ...
- 【C语言探索之旅】 第一部分第八课:第一个C语言小游戏
内容简介 1.课程大纲 2.第一部分第八课:第一个C语言小游戏 3.第一部分第九课预告: 函数 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写 ...
- 6、GNU makefile工程管理学习的一个例子
在之前我们已经学习了一个文件的编译过程,但是做过项目的都知道,一个工程中的源文件不计其数,其按类型.功能.模块会分别放在若干个目录中,而这些文件如何编译就需要有一个编译规则,虽然现在很多大型的项目都是 ...
- 一个例子理解Predicate、Consumer和Stream
一个需求: 把年龄大于20的学生的信息打印出来. 面向对象编程 public class Student { private String name; private int age; private ...
- 一个例子看懂所有nodejs的官方网络demo
今天看群里有人用AI技术写了个五子棋,正好用的socket.io,本身我自己很久没看nodejs了,再加上Tcp/IP的知识一直很弱,我就去官网看了下net.socket 发现之前以为懂的一个官方例子 ...
随机推荐
- JAVA中集合输出的四种方式
在JAVA中Collection输出有四种方式,分别如下: 一) Iterator输出. 该方式适用于Collection的所有子类. public class Hello { public stat ...
- {JavaScript}栈和堆内存,作用域
1.栈 stack”和“堆 heap”: 简单的来讲,stack上分配的内存系统自动释放,heap上分配的内存,系统不释放,哪怕程序退出,那一块内存还是在那里.stack一般是静态分配 ...
- python 装饰器和 functools 模块
转自:http://blog.jkey.lu/2013/03/15/python-decorator-and-functools-module/ 什么是装饰器? 在 python 语言里第一次看到装饰 ...
- Codeforces 626D Jerry's Protest 「数学组合」「数学概率」
题意: 一个袋子里装了n个球,每个球都有编号.甲乙二人从每次随机得从袋子里不放回的取出一个球,如果甲取出的球比乙取出的球编号大则甲胜,否则乙胜.保证球的编号xi各不相同.每轮比赛完了之后把取出的两球放 ...
- Js获取当前日期时间及时间相关操作
Js获取当前日期时间及时间格式 var myDate = new Date();myDate.getYear(); //获取当前年份(2位)myDate.getFullYear(); ...
- ORA-04031 With Leak in "OBJ STAT MEMO" Allocations Seen in V$SGASTAT on 10.2.0.5 (文档 ID 1350050.1)
APPLIES TO: Oracle Server - Enterprise Edition - Version: 10.2.0.5<max_ver> and later [Relea ...
- MFC创建非模态对话框并修改CStatic文字
//由IDD_STATUS_DIALOG创建一个对话框CDialog* pCheckNetStatusDlg = new CDialog(); pCheckNetStatusDlg->Creat ...
- 剑指Offer:面试题11——数值的整数次方(java实现)
题目描述: 实现函数double Power(double base, int exponent),求base的exponent次方,不得使用库函数,同时不需要考虑大数问题 思路:本题的重点考察内容是 ...
- Android开发-API指南-Android简介
Introduction to Android 英文原文:http://developer.android.com/intl/zh-cn/guide/index.html 采集日期:2014-4-16 ...
- 慕课网-安卓工程师初养成-4-11 Java循环跳转语句之 break
来源:http://www.imooc.com/code/1431 生活中,我们经常会因为某些原因中断既定的任务安排.如在参加 10000 米长跑时,才跑了 500 米就由于体力不支,需要退出比赛.在 ...