看的是爱酷学习网的视频:http://www.icoolxue.com/album/show/98
01
安装
1、先建mongoDB-data文件夹存数据
2、安装DB
3、设置环境变量:把bin目录:D:\mongodb\bin,添加到path下(;D:\mongodb\bin),好处是可以直接在cmd的命令行中输入mongod运行(这样也可检测),如果不设置环境变量,需要cd到当前目录下才能mongodb
启动
使用批处理文件来启动mongoDB,mongod.exe -dbpath d:\data
mongod help:查看常用的命令,mongodb启动命令参数说明:http://blog.csdn.net/fdipzone/article/details/7442162
27017:shell 客户端,28017:web
表:集合,行:文档
BSON对JSON的扩展,把json转为二进制码,增加了日期,浮点等json不支持的数据类型
nosql:集合(表),文档(行)。没有主键,关系数据库的每行的字段都是一样的,mongodb就不一定;关系数据库使用sql语句查询,mongodb使用find函数。
创建数据库:use foobar,只有加入相应的list,才会真正创建;
启动错误:32-bit servers don't have journaling enabled by default.由于上次的非正常关闭导致的,删掉上次的lock就好
启动shell
mongo 127.0.0.1:27017/admin
创建数据库:use foobar:只有加入list才会真正被创建;查看所有数据库:show dbs
查看所有文档:show collections
添加集合:db.persons.insert({name,'sfp'});mongodb会自动创建一个_id,生成集合system.indexes
查看指定文档的数据:db.persons.find();db.persons.findOne();
更新:db.persons.update({name:'sfp'},{name,'sfp1'}):查询器,修改器
另一种方式:var p=db.persons.findOne(); db.persons.update(p,{name,'sfp1'});这种更新内容是正常的
{age,'1'};更新后的文档只有age,所以才需要$set修改器
删除:db.persons.remove({})
02
删除集合:db.persons.drop()
删除数据库:db.dropDatebase()
全局help,数据库db.help(),集合db.persons.help()
命名的特殊情况:集合名(db-text),只能通过db.getCollection('db-text')得到此集合。
API:http://api.mongodb.org/js/2.7.7/
03
主要是讲增,删,改。
insert:可以手动加_id
批量插入:如果用[{},{}],则会插入一个文档,用0,1索引对应的{}。所以需要使用for循环来批量插入
save:与insert的区别,id相同时,save会变为更新语句,而insert会报错
db.persons.remove({}):集合被删除,索引不会被删除
数据量特别大的集合:drop再建索引,比remove效率高。如何为集合建立索引?
强硬文档替换式更新操作:文档替换;id冲突时会报错(原id有3,把id为2的改为3,则报错)
({},{},true):找不到,insert文档;能找到,update文档
({},{},false,true):批量更新,修改器需使用$set
修改器
$set | 有这个键,更新;没有这个键,添加。 |
$inc | 数字域,{age:27},{$inc:{age:1}} |
$unset | 去掉某个键,{age:27},{$uninc:{age":1}} |
$push | 数组键,1、给指定的数组键增加一个新的数值;2、如果不存在指定的数组键,则新建数组键;3、如果指定的不是数组键,则中断 |
$pushAll | 批量插入 |
$addToSet | 数组中存在要加的值,则忽略;不存在,则增加 |
$pop | 删除数组中指定的值,1:最后一个;-1:第一个 |
$pull | 删除数组中指定的值 |
$pullAll | 批量删除 |
$ | 数组定位器,{“books.type”:"js"},{$set:{"books.$.author":"uspcat"}} |
$addToSet和$each:批量更新数组,{$addToSet:{books:{$each:["js","db"]}}}
04
一个document创建后,会分配一定内存,会预留一部分内存。在预留的内存中修改时比较快;在未分配的内存中修改时比较慢。
runCommend:执行mongoDB的特殊函数
findAndModify:返回update或remove的文档
05
主要讲find,分页与排序,游标
返回指定的键:db.persons.find({},{_id:0,name:1,country:1}); _id默认返回,所以需要指定为0,不反回
查询条件:$lt,$lte,$gt,$gte,$ne
1、年龄在25-27之间:age:{$gte:25,$lte:27}
2、不是韩国学生的数学成绩:({cuntry:{$ne:korea}},{m:1})
包含$in,不包含$nin(只针对数组有效)
3、中国或美国:country:{$in:["china","us"]}
$or
4、语文高于85或英语高于90:$or:[{c:{$gt:85}},{e:{$gt:90}}]
5、正则查询,名字中包含li的:name:{/li/i}
$not(范围广,不局限于数组)
6、名字中没有li的:name:{$not:/li/i}
$all,index
7、喜欢mongodb,js的学生:books.{$all:["js","mongodb"]}
8、喜欢的第二本书是Java:"books.1":"java"
$size:不能与比较符一起使用(不足)
9、书为四本的学生:books:{$size:4}
10、数量大于3本的学生:由于$size的不足,所以需要三步
1、加size字段:{$set:{size:4}},false,true:批量增加字段
2、改变书籍的更新方式:{$push:{books:"oracle"},$inc:{size:1}}
3、利用$gt查询
11、喜欢书的数量:
1
2
3
4
5
|
var jim=db.persons.find({name: "jim" }); //得到的jim是游标,所以需要以下处理。在具体情况中,可以试验一下用数组可以不?返回的应该是数组。 while (jim.hasNext()){ var obj=jim.next(); print(obj.books.length); }<br> |
$lt,$lte,$gt,$gte,$ne,$or,$not,$all,$size
06
$slice:返回指定数组的内部值
12、2-4本书:books:{$slice:[1,3]}
$elemMatch:文档查询:对象嵌套
13、在K上过学:school:{school:"K",score:"A"},需要完全匹配;顺序也需要一致
解决办法:"school.score":"A","school.school":"K" 或者 也可以只写一个 "school.school":"K"
新问题:school:A,score:D,也会有结果。
解决办法:school:{$elemMath:{school:"K",score:"A"}}
$where:万能,性能低
14、年龄大于22,喜欢Java,在K上过学:find($("where"):function(){}),跟Java中的查询类似
$slice,$elemMatch,$where.
分页与排序
查前5:find().limit(5)
跨越5条:find().limit(5).skip(5)
排序:find().limit(5).skip(5).sort({name:1}),1为正序,-1为倒序
skip性能有问题---换种方式---加date字段,一般来说skip就够了。
游标
销毁条件:1、迭代完;2、客户端命令;3、10分钟不用。
快照
find({,$snapshot:true}),使用快照,则需使用高级查询。
如果不用快照的话,游标到了3,如果加了100个键,增大,则会把3放在最后,且扩容,把4变为3
用快照的话,不会发生以上的情况
高级查询
$query, $orderby, $maxsan, $min, $max, $hint, $explain, $snapshot
07
索引,管理,空间索引
索引(目录)
db.books.ensureIndex({number:1},{name:"bookname"}),-1:倒序
提高查询性能,影响插入性能,查多插少可考虑索引;索引不一定提高性能;排序也可加索引。
唯一索引:{unique:true}
建唯一索引前已有重复值:{dropDups:true}
本次查询指定索引:.hint({name:1})
管理
查看本次查询的信息:explain()
数据库中所有的索引:db.system.indexes.find(); 或者 db.system.namespace.find()
因为建索引会锁表,所以需要让索引在后台创建:{background:true}
删除索引:精确删除:db.runCommand({dropIndexes:'books',index:'name_1'});批量删除:db.runCommand({dropIndexes:'books',index:'*'})
08
空间索引
db.map.ensureIndex({'gis':'2d'},{min:-1,max:201})
距离最近:db.map.find({gis:{$near:[70,180]}}).limit(3)
方形内:db.map.find({gis:{$within:{$box:[[50,50],[190,190]]}}})
圆形内:db.map.find({gis:{$within:{$center:[[50,50],[190,190]]}}})
09
count+distinct+group,命令操作,固定集合,gridFs文件系统,服务器端脚本
count
1、查询美国学生人数:find({country:"usa"}).count()
distinct
2、有多少国家分别是什么:runCommand({distinct:"persons",key:"country"}).value(),去重
group
3、persons中每个国家学生数学成绩最好的学生,必须在90以上
1
2
3
4
5
6
7
8
9
10
|
<span style= "font-size: 16px;" >runCommand({group:{ ns: "persons" , //集合名 key:{ "country" : true }, //分组的键 initial:{m:0}, //初始化累加器 $reduce: function (doc,perv){}, //每个文档执行reduce方法,(组内本条记录,累加器数据) condition:{m:{$gt:90}}, //条件 finalize: function (){}, //完成器,把每个人的信息链接起来写一个描述赋值到m上。 } }) </span> |
4、如果有键country和counTry,则需
1
2
3
4
|
<span style= "font-size: 16px;" >$keyf: function (doc){ return {country:doc.counTry} //reduce函数也需要改一下, } </span> |
命令操作
删除list:db.runCommand({drop:"map"});
查询runCommand能够执行的所有命令:db.listCommands();(http://chenzhou123520.iteye.com/blog/1629946)
10
固定集合:固定的大小和文档数
特性:1、没索引,没_id;2、插入块,查询快;3、适合日志
创建大小100字节,存10个文档:db.createColllection("mycoll",{size:100,capped:true,max:10})
普通集合转固定集合:db.runCommand({convertToCapped:"persons",size:100})
反向排序:db.mycoll.find().sort({$natural:-1})
尾部游标(shell不支持,Java,php支持):不会自动销毁,等待结果
GridFS:把本地文件存入mongoDB,使用mongofiles.exe
上传:mongofiles -d foobar -l "e:\a.txt" put "a.txt"
查询:db.fs.chunks.find(); 或者 db.fs.files.find()
查看文件内容(VUE,shell不行):mongofiles -d foobar get "a.txt"
查看所有文件:mongofiles -d foobar list
删除文件(VUE,shell不行):mongofiles -d foobar delete "a.txt"
服务器端的脚本:主要讲的是shell中可以使用eval函数:db.eval("function(name){return name}","uspcat");
写入全局变量:db.system.js.insert({_id:name,value:"uspcat"}); db.eval("return name");
进而可以演变为存储方法:把"uspcat"写为"function(){}"
11
启动配置;导出,导入,运行时备份;Fsync锁,数据修复;用户管理,安全认证;
启动项:--dbpath; --port; --fork(保护进程的方式启动); --logpath; --config; -auth(安全认证)
利用config启动,并改端口为8888
mongodbconf.bat:mongod.exe --config mongod.conf
mongod.conf:dbpath = d:\data
port = 8888
启动mongodbconf.bat
停止shell:
1、右键关,不好,下次启动出问题后,把lock删了
2、ctrl+c
3、use admin, db.shutdownServer()
导出
mongoexport -d -c -o -csv -q --type<json/csv/txv>
mongoexport -d foobar -c port -o D:\persons.json
导出其他数据库的:mongoexport --host --port
导入
mongoimport --db foobar --collection persons --file d:\persons.json
运行时备份:
mongodump --host -d -o (有数据丢失,后面会解决)
恢复:mongorestore --host -d -directoryperdb
12
缓冲池:数据先写入缓冲池,再写入数据库,运行时备份只会备份数据库的,会丢失缓冲池的,所以需要锁
上锁:把缓冲池的数据全部写入数据库:db.runCommand({fsync:1,lock:1})
解锁:db.currentUp()
修复:db.repairDatabase()
用户管理,安全认证
添加用户:db.addUser("uspcat',"123")
需启用用户,才能查询数据库:db.auth("uspcat","123")
非admin用户不能用数据库命令:如show dbs.
删除用户:db.system.users.remove({user,"uspcat"})
13
主从复制,副本集
主从复制:数据库同步备份的集群技术
--master 主;--slave,--source 从
主:dbpath; port; bind_ip; master;
从:dbpath; port; bind_ip; source; slave;
配置好后,在主中写入数据,在从中可以看到。
默认会监听所有的数据库,通过
--only指定需复制的数据库
--slavedelay:同步延迟
--fastsync:把内存中的数据写入主数据库,进行从备份
--autoresync:不同步的重新同步,从才备份
--oplogsize(主):把主的操作记录到oplog,在从中运行一遍
动态添加和删除从的节点
查看:db.sources.find()
添加:db.sources.insert({"host":"127.0.0.1"8888"})
删除:db.sources.remove({"host":"127.0.0.1"8888"})
14
副本集
A故障后,B,C中选一个作为活跃,A恢复后,依然为备份。
设置副本集:
初始化副本集:
只有活跃点才能查询(rs.status()),备份的不能查询。
新的仲裁方式:备份的时间早的为活跃。
读写分离:slaveOkay:true; 在shell中不行,高级驱动可以
oplog:保存节点操作
主从:2台就可以,副本:3台以上。
15
这节讲的是分片,挺有意思的,自己试一下,综合性很强。
路由监听配置服务器,线画错了。
router.bat:mongos --port 1000 --configdb 127.0.0.1:2000
peizhi.bat:mongod --config peizhi.conf
peizhi.conf:dbpath = D:\mongodb\config //不用加""
port = 2000
bind_ip = 127.0.0.1
01.bat:mongod --config 01.conf
01.conf:dbpath = D:\mongodb\8081
port = 8081
bind_ip = 127.0.0.1
01_8081.bat:mongo 127.0.0.1:8081/admin
02.bat:mongod --config 02.conf
02.conf:dbpath = D:\mongodb\8082
port = 8082
bind_ip = 127.0.0.1
02_8082.bat:mongo 127.0.0.1:8082/admin
利用路由为集群增加分片:
打开四个bat,打开router的shell。
db.runCommand({addshard:"127.0.0.1:8081",allowLocal:true}); db.runCommand({addshard:"127.0.0.1:8082",allowLocal:true})
打开数据分片功能,为foobar打开分片功能:
use foobar, insert, db.runCommand({"enablesharding":"foobar"});
对集合进行分片:
db.runCommand({"shardCollection":"foobar.bar","key":{"_id":1}}) //使用数据库foobar中集合bar的key键进行分片
插入数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
function add(){ var i=0; for (;i<200000;i++){ db.bar.insert({ "age" :i+10, "name" : "jim" }) } } function add2(){ var i=0; for (;i<200000;i++){ db.bar.insert({ "age" :12, "name" : "tom" +i}) } } function add3(){ var i=0; for (;i<200000;i++){ db.bar.insert({ "age" :i+10, "name" : "lili" +i}) } } |
在01和02的shell中可以看到分配的数据。
在路由的shell中,输入db.peintShardingStatus();
在路由的shell中,use config, show dbs,db.shards.find(); //两个片区 db.mongos.find().
that's it!
更多的知识:配置服务器做成集群
片区与副本集结合使用