mongo数据库命令行操作应用分享

2017-01-05 11:17:48来源:oschina作者:0了凡0人点击

mongo数据库命令行操作应用分享


一、基础入门


1、打开mongo数据库客户端的程序访问,远程端的mongo数据库,默认进入的为test数据库。

配置了用户名和密码访问保证其安全性,需要使用用户名和密码,如下

切换数据库

2、insert操作


集合,这里就取集合名为“person”,要注意的就是文档是一个json的扩展(Bson)形式。


db.person.insert({"name":"jack","age":20})


执行成功后,如下图返回命令行以及客户端程序查看。


3、find操作


我们将数据插入后,肯定是要find出来,不然插了也白插,这里要注意两点:


① “_id": 这个字段是数据库默认给我们加的GUID,目的就是保证数据的唯一性。


② 严格的按照Bson的形式书写文档,不过也没关系,错误提示还是很强大的。

4、update操作


update方法的第一个参数为“查找的条件”,第二个参数为“更新的值”


5、remove操作


remove中如果不带参数将删除所有数据,呵呵,很危险的操作,在mongodb中是一个不可撤回的操作,三思而后行


二、细说增删改查


1、insert操作


1)单条插入


目前仅支持单条插入


2)批量插入


批量插入在代码中循环遍历插入


2、find操作


(1) >, >=, <, <=, !=, =。("$gt", "$gte", "$lt", "$lte", "$ne", "没有特殊关键字")

(2) "无关键字“, "$or", "$in","$nin"

(3)正则表达式查询

(4)组装查询where条件

3、update操作


(1)$inc修改器

(2) $set修改器

(3)upsert操作


这个可是mongodb创造出来的“词”,大家还记得update方法的第一次参数是“查询条件”吗?,那么这个upsert操作就是说:如果我没有查到,我就在数据库里面新增一条,其实这样也有好处,就是避免了我在数据库里面判断是update还是add操作,使用起来很简单


将update的第三个参数设为true即可。

(4)批量更新


在mongodb中如果匹配多条,默认的情况下只更新第一条,那么如果我们有需求必须批量更新,那么在mongodb中实现也是很简单的,在update的第四个参数中设为true即可


三、细说高级操作


1、聚合


(1)count

(2) distinct

(3) group

加上条件以及每行记录条数

(4) mapReduce


这玩意算是聚合函数中最复杂的了,不过复杂也好,越复杂就越灵活。


mapReduce其实是一种编程模型,用在分布式计算中,其中有一个“map”函数,一个”reduce“函数。


① map:


这个称为映射函数,里面会调用emit(key,value),集合会按照你指定的key进行映射分组。


② reduce:


这个称为简化函数,会对map分组后的数据进行分组简化,注意:在reduce(key,value)中的key就是


emit中的key,vlaue为emit分组后的emit(value)的集合,这里也就是很多{"count":1}的数组。


③ mapReduce:


这个就是最后执行的函数了,参数为map,reduce和一些可选参数。具体看图可知:




从图中我们可以看到如下信息:


result: "存放的集合名“;


input:传入文档的个数。


emit:此函数被调用的次数。


reduce:此函数被调用的次数。


output:最后返回文档的个数。


最后我们看一下“collecton”集合里面按姓名分组的情况。



2、游标


mongodb里面的游标有点类似我们说的C#里面延迟执行,比如:


var list=db.person.find();


针对这样的操作,list其实并没有获取到person中的文档,而是申明一个“查询结构”,等我们需要的时候通过


for或者next()一次性加载过来,然后让游标逐行读取,当我们枚举完了之后,游标销毁,之后我们在通过list获取时,


发现没有数据返回了。




当然我们的“查询构造”还可以搞的复杂点,比如分页,排序都可以加进去。


var single=db.person.find().sort({"name",1}).skip(2).limit(2);


那么这样的“查询构造”可以在我们需要执行的时候执行,大大提高了不必要的花销。



四、索引操作


好,今天分享下mongodb中关于索引的基本操作,我们日常做开发都避免不了要对程序进行性能优化,而程序的操作无非就是CURD,通常我们


又会花费50%的时间在R上面,因为Read操作对用户来说是非常敏感的,处理不好就会被人唾弃,呵呵。


从算法上来说有5种经典的查找,具体的可以参见我的算法速成系列,这其中就包括我们今天所说的“索引查找”,如果大家对sqlserver比较了解


的话,相信索引查找能给我们带来什么样的性能提升吧。


我们首先插入10w数据,上图说话:




一:性能分析函数(explain)


好了,数据已经插入成功,既然我们要做分析,肯定要有分析的工具,幸好mongodb中给我们提供了一个关键字叫做“explain",那么怎么用呢?


还是看图,注意,这里的name字段没有建立任何索引,这里我就查询一个“name10000”的姓名。



仔细看红色区域,有几个我们关心的key。


cursor:这里出现的是”BasicCursor",什么意思呢,就是说这里的查找采用的是“表扫描”,也就是顺序查找,很悲催啊。


nscanned: 这里是10w,也就是说数据库浏览了10w个文档,很恐怖吧,这样玩的话让人受不了啊。


n:这里是1,也就是最终返回了1个文档。


millis:这个就是我们最最最....关心的东西,总共耗时114毫秒。



二:建立索引(ensureIndex)


在10w条这么简单的集合中查找一个文档要114毫秒有一点点让人不能接收,好,那么我们该如何优化呢?mongodb中给


我们带来了索引查找,看看能不能让我们的查询一飞冲天.....



这里我们使用了ensureIndex在name上建立了索引。”1“:表示按照name进行升序,”-1“:表示按照name进行降序。


我的神啊,再来看看这些敏感信息。


cursor:这里出现的是”BtreeCursor",这么牛X,mongodb采用B树的结构来存放索引,索引名为后面的“name_1"。


nscanned: 我擦,数据库只浏览了一个文档就OK了。


n:直接定位返回。


millis:看看这个时间真的不敢相信,秒秒杀。



通过这个例子相信大家对索引也有了感官方面的认识了吧。



三:唯一索引


和sqlserver一样都可以建立唯一索引,重复的键值自然就不能插入,在mongodb中的使用方法是:


db.person.ensureIndex({"name":1},{"unique":true})。




四:组合索引


有时候我们的查询不是单条件的,可能是多条件,比如查找出生在‘1989-3-2’名字叫‘jack’的同学,那么我们可以建立“姓名”和"生日“


的联合索引来加速查询。



看到上图,大家或者也知道name跟birthday的不同,建立的索引也不同,升序和降序的顺序不同都会产生不同的索引,


那么我们可以用getindexes来查看下person集合中到底生成了那些索引。




此时我们肯定很好奇,到底查询优化器会使用哪个查询作为操作,呵呵,还是看看效果图:



看完上图我们要相信查询优化器,它给我们做出的选择往往是最优的,因为我们做查询时,查询优化器会使用我们建立的这些索引来创建查询方案,


如果某一个先执行完则其他查询方案被close掉,这种方案会被mongodb保存起来,当然如果非要用自己指定的查询方案,这也是


可以的,在mongodb中给我们提供了hint方法让我们可以暴力执行。




五: 删除索引


可能随着业务需求的变化,原先建立的索引可能没有存在的必要了,可能有的人想说没必要就没必要呗,但是请记住,索引会降低CUD这三


种操作的性能,因为这玩意需要实时维护,所以啥问题都要综合考虑一下,这里就把刚才建立的索引清空掉来演示一下:dropIndexes的使用。


五、主从复制


我们知道sql server能够做到读写分离,双机热备份和集群部署,当然mongodb也能做到,实际应用中我们不希望数据库采用单点部署,


如果碰到数据库宕机或者被毁灭性破坏那是多么的糟糕。



一:主从复制


1: 首先看看模型图




2: 从上面的图形中我们可以分析出这种架构有如下的好处:


<1> 数据备份。


<2> 数据恢复。


<3> 读写分离。



3:下面我们就一一实践


实际应用中我们肯定是多服务器部署,限于自己懒的装虚拟机,就在一台机器上实践了。


第一步:我们把mongodb文件夹放在D盘和E盘,模拟放在多服务器上。


第二步:启动D盘上的mongodb,把该数据库指定为主数据库,其实命令很简单:>mongodb --dbpath='XXX' --master,


端口还是默认的27017.



第三步:同样的方式启动E盘上的mongodb,指定该数据库为从属数据库,命令也很简单,当然我们要换一个端口,比如:8888。


source 表示主数据库的地址。


>mongod --dbpath=xxxx --port=8888 --slave --source=127.0.0.1:27017



第四步:从图中的红色区域我们发现了一条:“applied 1 operations"这样的语句,并且发生的时间相隔10s,也就说明从属数据库每10s


就向主数据库同步数据,同步依据也就是寻找主数据库的”OpLog“日志,可以在图中红色区域内发现”sync_pullOpLog“字样。


接下来我们要做的就是测试,惊讶的发现数据已经同步更新,爽啊。




4: 如果我还想增加一台从属数据库,但是我不想在启动时就指定,而是后期指定,那么mongodb可否做的到呢?答案肯定是可以的。


我们的主或者从属数据库中都有一个叫做local的集合,主要是用于存放内部复制信息。


好,那么我们就试一下,我在F盘再拷贝一份mongodb的运行程序,cmd窗口好多啊,大家不要搞乱了。



看上面的log,提示没有主数据库,没关系,某一天我们良心发现,给他后期补贴一下,哈哈,再开一个cmd窗口,语句也就是


在sources中add一个host地址,最后发现数据也同步到127.0.0.1:5555这台从属数据库中....




5: 读写分离


这种手段在大一点的架构中都有实现,在mongodb中其实很简单,在默认的情况下,从属数据库不支持数据的读取,但是没关系,


在驱动中给我们提供了一个叫做“slaveOkay"来让我们可以显示的读取从属数据库来减轻主数据库的性能压力,这里就不演示了。



二:副本集


这个也是很牛X的主从集群,不过跟上面的集群还是有两点区别的。


<1>: 该集群没有特定的主数据库。


<2>: 如果哪个主数据库宕机了,集群中就会推选出一个从属数据库作为主数据库顶上,这就具备了自动故障恢复功能,很牛X的啊。


好,我们现在就来试一下,首先把所有的cmd窗口关掉重新来,清掉db下的所有文件。



第一步: 既然我们要建立集群,就得取个集群名字,这里就取我们的公司名shopex, --replSet表示让服务器知道shopex下还有其他数据库,


这里就把D盘里面的mongodb程序打开,端口为2222。指定端口为3333是shopex集群下的另一个数据库服务器。




第二步: 既然上面说3333是另一个数据库服务器,不要急,现在就来开,这里把E盘的mongodb程序打开。




第三步: ok,看看上面的日志红色区域,似乎我们还没有做完,是的,log信息告诉我们要初始化一下“副本集“,既然日志这么说,那我也就


这么做,随便连接一下哪个服务器都行,不过一定要进入admin集合。




第四步: 开启成功后,我们要看看谁才能成为主数据库服务器,可以看到端口为2222的已经成为主数据库服务器。




第五步:我们知道sql server里面有一个叫做仲裁服务器,那么mongodb中也是有的,跟sql server一样,仲裁只参与投票选举,这里我们


把F盘的mongodb作为仲裁服务器,然后指定shopex集群中的任一个服务器端口,这里就指定2222。




然后我们在admin集合中使用rs.addArb()追加即可。



追加好了之后,我们使用rs.status()来查看下集群中的服务器状态,图中我们可以清楚的看到谁是主,还是从,还是仲裁。




不是说该集群有自动故障恢复吗?那么我们就可以来试一下,在2222端口的cmd服务器按Ctrl+C来KO掉该服务器,立马我们发现


在3333端口的从属服务器即可顶上,最后大家也可以再次使用rs.status()来看下集群中服务器的状态。


六、分片技术


在mongodb里面存在另一种集群,就是分片技术,跟sql server的表分区类似,我们知道当数据量达到T级别的时候,我们的磁盘,内存


就吃不消了,针对这样的场景我们该如何应对。



一:分片


mongodb采用将集合进行拆分,然后将拆分的数据均摊到几个片上的一种解决方案。




下面我对这张图解释一下:


人脸:代表客户端,客户端肯定说,你数据库分片不分片跟我没关系,我叫你干啥就干啥,没什么好商量的。


mongos: 首先我们要了解”片键“的概念,也就是说拆分集合的依据是什么?按照什么键值进行拆分集合....


好了,mongos就是一个路由服务器,它会根据管理员设置的“片键”将数据分摊到自己管理的mongod集群,数据


和片的对应关系以及相应的配置信息保存在"config服务器"上。


mongod:一个普通的数据库实例,如果不分片的话,我们会直接连上mongod。



二: 实战


首先我们准备4个mongodb程序,我这里是均摊在C,D,E,F盘上,当然你也可以做多个文件夹的形式。


1:开启config服务器


先前也说了,mongos要把mongod之间的配置放到config服务器里面,理所当然首先开启它,我这里就建立2222端口。




2: 开启mongos服务器


这里要注意的是我们开启的是mongos,不是mongod,同时指定下config服务器,这里我就开启D盘上的mongodb,端口3333。




3:启动mongod服务器


对分片来说,也就是要添加片了,这里开启E,F盘的mongodb,端口为:4444,5555。




4: 服务配置


哈哈,是不是很兴奋,还差最后一点配置我们就可以大功告成。


<1> 先前图中也可以看到,我们client直接跟mongos打交道,也就说明我们要连接mongos服务器,然后将4444,5555的mongod


交给mongos,添加分片也就是addshard()。



这里要注意的是,在addshard中,我们也可以添加副本集,这样能达到更高的稳定性。



<2>片已经集群了,但是mongos不知道该如何切分数据,也就是我们先前所说的片键,在mongodb中设置片键要做两步


①:开启数据库分片功能,命令很简单 enablesharding(),这里我就开启test数据库。


②:指定集合中分片的片键,这里我就指定为person.name字段。




5: 查看效果


好了,至此我们的分片操作全部结束,接下来我们通过mongos向mongodb插入10w记录,然后通过printShardingStatus命令


查看mongodb的数据分片情况。



这里主要看三点信息:


① shards: 我们清楚的看到已经别分为两个片了,shard0000和shard0001。


② databases: 这里有个partitioned字段表示是否分区,这里清楚的看到test已经分区。


③ chunks: 这个很有意思,我们发现集合被砍成四段:


无穷小 —— jack0,jack0 ——jack234813,jack234813——jack9999,jack9999——无穷大。


分区情况为:3:1,从后面的 on shardXXXX也能看得出。

七、运维技术


这一篇我们以管理员的视角来看mongodb,作为一名管理员,我们经常接触到的主要有4个方面:


1. 安装部署


2. 状态监控


3. 安全认证


4. 备份和恢复,


下面我们就一点一点的讲解。



一:安装部署


我之前的文章都是采用console程序来承载,不过在生产环境中这并不是最佳实践,谁也不愿意在机器重启后满地找牙似找mongodb,


在mongodb里面提供了一个叫做“服务寄宿”的模式,我想如果大家对wcf比较熟悉的话很容易听懂。好了,我们实践一下,这里我开一下D盘


里面的mongodb。




这里要注意的有两点:


<1> logpath: 当我们使用服务寄宿的时候,用眼睛都能想明白肯定不会用console来承载日志信息了。


<2> install:开启安装服务寄宿,很happy啊,把管理员的手工操作降低到最小,感谢mongodb。



好了,console程序叫我看log日志,那我就看看,发现mongodb已经提示我们如何开启mongodb,接着我照做就是了。




还要提醒大家一点的就是,这些命令参数很多很复杂也就很容易忘,不过没关系,数据库给我们提供了一个help方法,我们可以


拿mongod和mongo说事。


mongod:




mongo:




二:状态监控


监控可以让我们实时的了解数据库的健康状况以及性能调优,在mongodb里面给我们提供了三种方式。


1:http监视器


这个我在先前的文章中也提到了,这里就不赘述了。


2:serverStatus()


这个函数可以获取到mongodb的服务器统计信息,其中包括 :全局锁,索引,用户操作行为等等这些统计信息,对管理员来说非常


重要,具体的参数含义可以参考园友:http://www.cnblogs.com/xuegang/archive/2011/10/13/2210339.html


这里还是截个图混个眼熟。




3:mongostat


前面那些统计信息再牛X,那也是静态统计,不能让我观看实时数据变化,还好,mongodb里面提供了这里要说的mongodstat


监视器,这玩意会每秒刷新,在实际生产环境中大有用处,还是截张图,很有意思,是不是感觉大军压境了。




三:安全认证


作为数据库软件,我们肯定不想谁都可以访问,为了确保数据的安全,mongodb也会像其他的数据库软件一样可以采用用户


验证的方法,那么该怎么做呢?其实很简单,mongodb提供了addUser方法,还有一个注意点就是如果在admin数据库中添加


将会被视为“超级管理员”。



上面的admin用户将会被视为超级管理员,“jack”用户追加的第三个参数表示是否是“只读用户”,好了,该添加的我们都添加了,


我们第一次登录时不是采用验证模式,现在我们使用--reinstall重启服务并以--auth验证模式登录。



好了,我们进入test集合翻翻数据看看情况,我们发现jack用户始终都是没有写入的权限,不管是授权或者未授权。




四:备份和恢复


这玩意的重要性我想都不需要我来说了吧,这玩意要是搞不好会死人的,mongodb里面常用的手段有3种。


1: 直接copy


这个算是最简单的了,不过要注意一点,在服务器运行的情况下直接copy是很有风险的,可能copy出来时,数据已经遭到


破坏,唯一能保证的就是要暂时关闭下服务器,copy完后重开。


2:mongodump和mongorestore


这个是mongo给我们提供的内置工具,很好用,能保证在不关闭服务器的情况下copy数据。


为了操作方便,我们先删除授权用户。




好了,我们转入正题,这里我先在D盘建立一个backup文件夹用于存放test数据库。



快看,数据已经备份过来了,太爽了,现在我们用mongorestore恢复过去,记住啊,它是不用关闭机器的。



提一点的就是 drop选项,这里是说我将test数据恢复之前先删除原有数据库里面的数据,同样大家可以通过help查看。



3:主从复制


这个我在上上篇有所介绍,这里也不赘述了。



其实上面的1,2两点都不能保证获取数据的实时性,因为我们在备份的时候可能还有数据灌在内存中不出来,那么我们


想说能不能把数据暴力的刷到硬盘上,当然是可以的,mongodb给我们提供了fsync+lock机制就能满足我们提的需求。


fsync+lock首先会把缓冲区数据暴力刷入硬盘,然后给数据库一个写入锁,其他实例的写入操作全部被阻塞,直到fsync


+lock释放锁为止。


这里就不测试了。


加锁:db.runCommand({"fsync":1,"lock":1})


释放锁: db.$cmd.unlock.findOne()

八、驱动实践


java代码调用,见< mongo数据项目应用 >

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台