代码改变世界

mongodb学习笔记

2013-08-18 10:56  hduhans  阅读(225)  评论(0)    收藏  举报

说明:

① mongodb是基于bson数据格式,存储格式分为:库(db)->集合(collection)->JSON ,分别与关系型数据库中的:数据库(db)->表(table)->记录(record)对应

② 循环插入操作数据:

for(i=1;i<=10;i++){
  db.c1.insert({name:"user"+i});
}

 

一、mongodb常用操作命令大全

1、新增。

     ① insert命令:db.c1.insert({name:"hans"})  

     ② save命令:db.c1.save({name:"hans"})  

说明:save命令当键值对包含_id时,会先查询是否包含此_id的数据,若包含,则修改(删除旧数据,插入新数据),否则新增;而insert命令执行插入操作时,若_id重复,则报异常

2、修改。update命令:

  1) db.c1.update({name:"hans"},{name:"hduhans"})  --将c1集合下所有name="hans"的记录更改为name="hduhans"

  2) db.c1.update({name:"hans"},{$set:{name:"hduhans"}})  --同上,但修改结果可理解为不删除,只修改set内容中的字段,若不存在此字段,则新增字段

注:update方法有四个参数,db.collections.update(criteria,objNew,upsert,multi)  详见下文

3、删除。remove命令:

  1) db.c1.remove()  --移除c1集合中的所有记录

  2) db.c1.remove({name:"hans"})  --移除c1集合中name="hans"的记录

说明:remove命令只会删除集合中的数据,不会删除集合本身(命令 show collections仍然可以看到集合的存在),删除集合使用命令drop,如db.c1.drop()

4、查找。find()命令:

  1) db.c1.find()  --查找c1集合中所有记录

  2) db.c1.find({name:"hans"},{name:1,age:1})  --查找c1集合中name="hans"的所有记录中的name和age两个字段值

注:id系统默认会显示查询结果,如不需显示_id,可强制指定 _id:0

 ----------------------------------------------------以下是魔术方法----------------------------------------------------------------

5、范围限定。

  例:db.c1.find({age:{$gt:5}})   --查询c1集合中age>5的记录

注:$gt-大于 $lt-小于 $gte-大于等于 $lte-小于等于 $ne-不等于

6、计算数目。count命令:

  1) db.c1.count()  --查询c1集合的所有记录数   

  2) db.c1.find({age:{$gte:18}}).count()   --查询c1集合中age>18的所有记录数

注:count()命令其实有参数,默认为0,默认忽略limit、skip等命令的影响;参数为1时,不忽略影响

7、排序。sort命令:

  db.c1.sort({age:1})  --查询c1集合所有记录并按age的升序排序

注:1-升序 -1-降序

8、跳过开头若干结果。skip命令:

  db.c1.find().skip(2)   --查询c1集合中从第3个记录开始的所有记录

9、限制结果数。limit命令:

  db.c1.find().limit(3)  --查询c1集合中前3个记录

注:1) mongodb中没有limit(2,3)这种语法,如确实需要查询从第3个开始的连续3个记录,可结合skip()进行操作,具体写法:db.c1.find().skip(2).limit(3) 

  2) 可以结合排序 db.c1.find().skip(2).limit(3).sort({age:-1})   --注意mongodb的操作顺序是先排序后筛选,留意此现象

  3) 可以结合数据统计 db.c1.find().skip(2).limit(3).count(1)  --注意此处count添加参数1,具体参看count命令

10、数组内容匹配筛选。$all操作符:

  例:a、执行db.c2.insert({name:"user1",post:[1,2,3,4,5]})

    b、db.c2.find({post:{$all:[1,3,5]}})   --查询c2集合中同时包含帖子编号为1,3和5的记录

注:此命令仅针对数组

11、检查字段是否存在。$exists操作符:

  db.c1.find({name:{$exists:1}})   --查询c1集合中包含name字段的所有记录

注:0-不包含字段 1-包含字段

12、取余。$mod操作符:

  db.c1.find({age:{$mod:[2,1]}})   --查询c1集合中所有age对2取余值为1的记录

13、多值匹配。$in和$nin操作符:

  1) db.c1.find({age:{$in:[5,8,9]}})  --查询c1集合中所有age等于5或8或9的所有记录

  2) db.c1.find({age:{$nin:[5,8,9]}})  --查询c1集合中所有age不等于5且不等于8且不等于9的所有记录

注:$in-值在范围内  $nin-值不在范围内

14、或者。$or和$nor操作符:

  1) db.c1.find({$or:[{name:"user2"},{name:"user3"}]})  --查询c1集合中name="user2"或者name="user3"的所有记录

  2) db.c1.find({$nor:[{name:"user2"},{name:"user3"}]})  --查询c1集合中name!="user2"且name!="user3"的所有记录

注:$or和$nor操作符位于外侧,同关系数据库中的in和not in

15、数组长度筛选。$size操作符:

  db.c2.find({post:{$size:3}})   --查询c2集合中post字段数组长度为3的所有记录

注:$size操作符仅针对数组有效

16、正则匹配。

  db.c1.find({name:/user/i})   --查询c1集合中name值包含"user"并且不区分大小写的所有记录

17、剔除重复。distinct命令:

  db.c1.distinct("name")   --查询c1集合中所有name不重复的值

18、数组子元素的查询。$elemMatch操作符:

  1) 插入数据:db.c3.insert({name:"user1",post:[{tit:1},{tit:2},{tit:3}]})

  2) db.c3.find({post:{$elemMatch:{tit:1,tit:2}}})   ---查询c3集合中post字段中同时包含tit=1和tit=2的记录

注:$elemMatch操作符仅针对数组,可用.代替。如2)也可写为:db.c3.find({"post.tit":1,"post.tit":2}) 

19、数组子元素查询前N个元素。$slice操作符:

  db.c3.find({name:"user1"},{post:{$slice:2}})  ---查询c3集合中name="user1"且post取前2个元素的所有记录

注:1) n-前3个元素 -n后三个元素 (n为正整数)

  2) [n,m] 从第n+1个元素开始取连续的m个元素

  ----------------------------------------------------以下是更新方法----------------------------------------------------------------

20、修改方法。db.collections.update(criteria,objNew,upsert,multi): 

  参数说明:criteria-查询条件的对象

         objNew-更新内容的对象

         upsert-值为0或1  1表示根据查询条件查询不到对象时,则新增objNew对象  此处建议值:0。 默认值:0

       multi-值为0或1  根据查询条件查询出的结果数目大于1时,multi可控制更新只第一条数据还是更新所有数据   multi-1需配合objNew的魔术变量(如:$set)方可使用。 默认值:0

21、修改器。$inc操作符:

  db.c1.update({},{$inc:{score:10}},0,1)   --将c1集合中所有记录的score值加10(没有score字段视为score=0,新增字段)

21、删除字段。$unset操作符:

  db.c1.update({},{$unset:{score:1},0,1})   --将c1集合中所有记录的score字段删除

22、插入默认单个可重复数组元素。$push操作符:

  db.c2.update({name:"user1"},{$push:{post:9}})   --将c2集合中name="user1"记录中的post字段追加可重复数组元素9

注:1) 允许插入重复值,插入不重复数组元素用$addToSet

  2) 不允许插入多个值,如$push:{post:[8,9,10]},系统则会将[8,9,10]作为一个子数组插入,插入多个值用$pushAll或结合$each魔术方法,详见下文

23、插入默认单个不可重复数组元素。$addToSet操作符:

  1) db.c2.update({name:"user1"},{$addToSet:{post:6}})   --将c2集合中name="user1"记录中的post字段追加不重复数组元素6

  2) db.c2.update({name:"user1"},{$addToSet:{post:{$each:[7,8,9]}}})   --将c2集合中name="user1"记录中的post字段同时追加不重复数组元素7,8,9

24、插入多个数组元素。$pushAll操作符:

  db.c2.update({name:"user1"},{$pushAll:{post:[5,6,7]}})  --将c2集合中name="user1"记录中的post字段追加数组元素5,6,7

25、删除数组首尾元素。$pop操作符:

  1) db.c2.pop({name:"user1"},{$pop:{post:1}})  --将c2集合中name="user1"记录中的post字段数组最后一个元素删除

  2) db.c2.pop({name:"user1"},{$pop:{post:-1}})   --将c2集合中name="user1"记录中的post字段数组第一个元素删除

注:1) 1-删除最后一个数组元素  -1-删除第一个数组元素

  2) 貌似不能一次性删除多个元素

26、删除数组指定元素。$pull和$pullAll操作符:

  1) db.c2.update({name:"user1"},{$pull:{post:4}})  --将c2集合中name="user1"记录中的post字段数组中的元素4删除

  2) db.c2.update({name:"user1"},{$pull:{post:{$gt:5}}})   --将c2集合中name="user1"记录中的post字段数组中大于5的元素删除

  3) db.c2.update({name:"user1"},{$pullAll:{post:[3,4]}})  --将c2集合中name="user1"记录中post字段数组中元素3和元素4删除

注:$pull字段可结合前面的魔术方法

27、更改字段名称。$rename操作符:

  db.c2.update({name:"user1"},{$rename:{"post":"new_post"}})   --将c2集合中name="user1"记录中的"post"字段名改为"new_post"

28、更改字段数组元素值。$操作符:

  1) 插入数据:db.c2.insert({name:"user1"},{post:[{tit:"Linux"},{tit:"Windows"s},{tit:"Mac OS"}]})

  2) db.c2.update({"post.tit":"Linux"},{$set:{"post.$.tit":"Linux OS"}})   --将c2集合中字段post数组中存在tit="Linux"的记录的对应元素标题改为"Linux OS"

 

二、mongodb性能优化

1、创建固定集合。固定集合的优点:1) 插入速度极快  2) 顺序查找输出速度极快 3) 方便实现插入最新数据的同时淘汰最早的数据(很适合存储日志信息)

  1) db.createCollection("c1",{capped:true,max:10,size:10000})   --创建一个名为 "c1",大小为10K,最大记录数为10的一个固定集合

  2) db.runCommand({convertToCapped:"c1",size:10000,max:50})   --将普通集合c1更改为固定集合,大小为10K,最大记录数为50

注:db.c1.stats() 可查看c1集合的详细信息,是否为固定集合

 2、GridFS文件操作。

  1) dos进入mongodb安装文件所在位置,执行mongofiles -h可查看相关帮助

  2) mongofiles put D:\desktop\hans.rar   --将文件D:\Destop\hans.rar文件上传至mongodb

  3) 运行mongo,执行show collections,发现存在fs.files和fs.chunks集合,分别对应文件信息和文件具体二进制块

 3、建立索引。

  1) db.c1.ensureIndex({name:1})   --在c1集合中的name字段上建立索引

  2) db.c1.ensureIndex({name:1},{background:true})   --功能同上,区别是建立索引过程在后台进行,适合对大数据建立索引

  3) db.c1.ensureIndex({age:1},{unique:1})   --功能同上,区别是建立唯一索引,即age字段值不能重复

  4) db.c1.getIndexKeys()  --查看集合c1的所有索引  getIndexes() 查看详细索引信息

  5) db.c1.dropIndex({age:1})    --删除age索引,dropIndexes() 删除所有索引

4、explain执行计划。可查看系统对查询请求的处理详细信息。

  db.c1.find({name:"user6"}).explain()   --分析系统对此查询语句的处理信息

注: "nscanned"--被扫描的文档数量(可对比建立索引前后对同一查询的文档扫描数)

   "n"--返回文档数量

   "millis"--查询用时(毫秒)

5、慢查询记录。profile用户记录慢查询记录,便于对慢查询进行分析和优化。

   ① 开启Profiling功能。

    1) db.getProfilingLevel()  --获取当前的profile级别

    2) db.setProfilingLevel(1,(50))  --客户端设置当前profile级别,记录查询时间大于50ms的操作 

   ② 慢查询记录保存在集合system.profile中。

注:Profiling的level {0-不开启,1-记录慢命令(默认>100ms),2-记录所有命令}

------------------------------------------------------优化建议--------------------------------------------------------------------------

6、结合上述功能,mongodb性能优化建议:

  1) 创建索引(适用于查询多、修改少的集合)

  2) 限定查询返回的条数 

  3) 避免查询所有字段,只查询返回需要的字段

  4) 使用固定集合cappedcollection

  5) 开启Profiling慢日志分析

----------------------------------------------------------------------------------------------------------------------------------

7、服务监控。

  1) mongostat.exe。该程序会每秒刷新mongodb服务状态,包含各种参数。

  2) mongosniff.exe。该程序会监控mongodb客户端与服务端通信的情况。

 

三、mongodb常用管理

1、导入导出。

   ① 导出。执行程序mongoexport.exe。

    1) mongoexport -d test - c c1 -o D:\test.c1.txt  --将数据库test中的c1集合的数据导出至D:\test.c1.txt

    2) mongoexport -d test - c -q "{age:{$gte:18}}" c1 -o D:\test.c1.txt   --功能同上,区别是只导出年龄>=18的记录

   ② 导入。执行程序mongoimport.exe。

    1) mongoimport -d test -c c1 --file D:\test.c1.txt  --将文件D:\test.c1.txt导入至数据库test中的c1集合中

    2) mongoimport -d test -c c1 --file D:\test.c1.txt  --drop  --功能同上,区别是导入数据时若存在c1集合则先删除,为确保导入顺利进行(_id不能重复) 

 2、数据备份与恢复。

   ① 数据备份。执行程序mongodump.exe。

    mongodump -d test -o D:\save   --将数据库test备份至D:\save\test

   ② 数据恢复。执行程序mongorestore.exe。

    mongorestore -d test D:\save\test   --从文件D:\save\test恢复至数据库test

 3、用户授权。mongodb默认是没有用户授权,默认登陆账户admin。

   ① 修改服务启动参数(Windows)。

    在注册表中找到mongodb服务,路径HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\MongoDB\ImagePath,在ImagePath参数中增加--auth,如:F:\mongodb\mongod.exe --dbpath F:\mongodb\data --logpath F:\mongodb\logs\mongodb.logs --auth --service。修改完重启mongodb服务。

   ② 授权超级管理员。重新启动mongo,会发现数据库admin。

    1) use admin   --切换admin为当前操作数据库

    2) db.addUser("root","123")  --admin数据库添加超级管理员root,密码123

    3) db.auth("root","123")   --超级管理员登陆

   ③  授权普通数据表(集合)管理员。

    1) use test   --切换test为当前操作数据库

    2) db.addUser("root1","123")   --test数据库添加数据表管理员root,密码123

    3) db.auth("root1","123")   --数据表管理员登陆

注:1) 超级管理员登陆时,admin必须切换为当前操作数据库。

  2) 普通数据表管理员登陆时,对应的数据库必须切换为当前操作数据库。

  3) 超级管理员拥有所有权限,数据表管理员只拥有相应表的管理权限。

 

四、mongodb数据架构

1、主从数据库设置。从服务器会实时同步主服务的数据,从服务器数据只读。

   ① 设置主服务器。mongodb安装目录中新建数据目录data1和日志目录dblog1和日志文件dblog1\master.log。

    1) mongod --master --dbpath F:\mongodb\data1 --logpath F:\mongodb\dblog1\master.log --port 20001      --开启主服务器服务,端口20001

    2) mongo --port 20001   --连接主服务器

   ② 设置从服务器。mongodb安装目录中新建数据目录data2和日志目录dblog2和日志文件dblog2\slave.log。

    1) mongodb --slave --source 127.0.0.1:20001 --dbpath F:\mongodb\data2 --logpath F:\mongodb\dblog2\slave.log --port 20002   --开启从服务器,连接上述主服务器,端口20002

    2) mongo --port 20002   --连接从服务器

注:可结合用户验证,可将主服务器和从服务器分别设置为系统服务,随系统启动而启动。

2、数据库副本集。副本集可以在主服务器发生故障时根据设定自动推荐某个副本作为临时主服务器,保证数据服务的不间断性。

   1) 本例子建立含三个数据服务的集群。mongodb根目录新建data和log,分别建立子目录data1、data2、data3和dblog1、dblog2、dblog3。

   2) 分别开启三个数据服务。

    a、mongod --replSet rs1 --dbpath F:\mongodb\data\data1 --logpath F:\mongodb\log\dblog1 --port 20001

    b、mongod --replSet rs1 --dbpath F:\mongodb\data\data2 --logpath F:\mongodb\log\dblog2 --port 20002

    c、mongod --replSet rs1 --dbpath F:\mongodb\data\data3 --logpath F:\mongodb\log\dblog3 --port 20003

   3) 集群配置。

    a、mongo --port 20001   --连接端口为20001的服务器(配置时可任意连接一台服务器)

    b、config_rs1={"_id":"rs1",members:[{"_id":0,host:"127.0.0.1:20001",priority:3},{"_id":1,host:"127.0.0.1:20002",priority:2},{"_id":2,host:"127.0.0.1:20003",priority:1}]}   --配置内容 priority越大优先级越高

    c、rs.initiate(config_rs1)   --初始化配置

   4) 配置完成后,优先级最高的那台服务器会被选择为主服务器,其余均为从服务器。从服务器会实时备份主服务器的数据。从服务器需要查看备份数据时,需执行 rs.slaveOk()

   5) 当20001服务器发生故障而不能继续提供数据服务时,剩余的集群服务器会根据优先级配置选择一台作为主服务器,继续提供服务。