#region 第一讲
Windows 下载安装
1.下载地址: http://www.mongodb.org/downloads
2.安装注意,在安装之前,在硬盘上建立一个目录存放 MongoDB 安装文件
3.添加 MongoDBDATA,用于保存数据
4.执行CMD命令
4.1 bin\mongod.exe --dbpath MongoDBDATA
4.2 作为 windows服务
bin\mongod.exe --dbpath "\"MongoDBDATA"\" --install
5.设置环境变量
path中添加 ;MongoDB\bin
6.启动数据库服务
根据自己需要修改 mongodb.bat 文件
mongod --dbpath MongoDBDATA
7.启动数据库服务的配置文件
http://www.uspcat.com/forum.php?mod=viewthread&tid=7722&extra=page%3D1
Shell基本操作
启动 shell
mongo 127.0.0.1:27017
1.创建一个数据库
use [dbName]
如果什么都不干的话,数据库文件是不会建立的
2.查看所有数据库
show dbs
3.给指定数据库添加集合并且添加记录
db.[documentName].insert({...})
4.查看数据库中的所有文档
show collections
db.[documentName].find()
db.[documentName].findOne()
5.查询制定文档的数据
6.更新文档数据(默认是更新第一条记录)
db.[documentName].update({查询器},{更新器})
db.[documentName].update({name:""},{$set:{name:"extjs4.1"}})
var p = db.[documentName].findOne()
db.[documentName].update(p,{"name","value"})
7.删除文档中的数据
db.[documentName].remove({})
8.删除库中的集合
db.[documentName].drop()
9.删除数据库
db.dropDatabase()
10.Shell的help
db.help()
db.getName()
db.status()
db.[documentName].help()
11.mongoDB的API
http://api.mongodb.org/js/2.1.1/index.html
* 数据库和集合命名
1.不能使用特殊字符
2.应全部小写
3.最多64个字节
4.数据库名不能与现有系统保留库同名,如 admin,local及config
* shell 可以用 eval
BSON扩充的数据类型
BSON是JSON的扩展,他先新增了日期,浮点等JSON不支持的数据类型
* MongoVUE
破解方法:找到 "4FF78130",把里面的子项全部删除,删除之后就又可以用14天
安装
#endregion 第一讲
#region 第二讲
Document 数据插入
1.插入文档
2.批量插入文档
不支持批量插入,可以通过高级语言或 for循环
3.Save操作
insert时,如果_id相同,则会报错
Document 数据删除
1.删除集合中的所有数据
db.[documentName].remove()
集合本身和索引不会被删除
2.根据条件删除
db.[documentName].remove({})
3.小技巧
如果想清除一个数据量十分庞大的集合
直接删除该集合并重新建立索引的办法比直接用remove的效率高得多
Document 数据更新
1.强硬的文档替换式更新操作
db.[documentName].update({查询器},{修改器})
强硬的更新会用新的文档代替老的文档
db.Tickets.update({Multiple:10},{"Content":"100}),更新之后,就只有 Content 了
2.主键冲突的时候会报错并且停止更新操作
3.insertOrUpdate操作
目的:查询器查询出来的数据就更新,查不出来就执行插入操作
做法:db.[documentName].update({查询器},{修改器})
4.批量更新操作
默认情况下,修改器只会修改第一条查询出来的记录
批量: db.[documentName].update({查询器},{$set:{name:"33"}},false,true)
5.修改器
$set:{field:value,field1:value1,...} 如果存在则更新,不存在则添加
$inc:{numberField:numberValue}
$unset:{field:value}删除指定的字段,
$push:{field:value} 如果操作的是数组则添加新值,如果指定的field不存在,则创建数组,如果filed不是数组,则报错
$pushAll:{field:arry} 可以对数组类型批量添加新值
$addToSet:{field:value} 目标数组存在相同的项则不操作,不存在则加进去
$pop:{arryField:value} value=1 删除arryField中的最后一个数值,value=-1删除arryField中第一个数值
$pull:{arryField:value} 从 arryField中删除指定的value
$pullALL:{arryField:arry} 从 arryField中删除arry
db.[documentName].update({"books.type":"js"},{$set:{"books.$.author":"USPCAT"}})
6.$addToSet与$each结合完成批量数组更新
db.[documentName].update({查询器}, {$addToSet:{books:{$seach:["JS","DB"]}}})
7.内存分配与查询效率
当document被创建的时候DB为其分配内存和预留内存,当修改操作不超过预留内存的时候则速度非常快,
如果document超过了分配的内存时,就要分配新内存,这时候查询就会慢
8.runCommand函数和findAndModify函数
runCommand可以执行 mongoDB 中的特殊函数
findAndModify就是特殊函数之一,它用于返回update或remove后的文档
runCommand({findAndModify":"processes",
query:{查询器},
sort(排序),
new:true,
update:{更新器}
remove:true
}).value
ps = db.runCommand({
"findAndModify":"persons",
"query":{"name":"text"},
"update":{"$set":{"email":"1221"}},
"new":true
}).value
#endregion 第二讲
#region 第三讲
Find
操作
$lt 小于
$lte 小于等于
$gt 大于
$gte 大于等于
$ne 不等于
$in 包含
$nin 不包含
$or 或
db.[documentName].find({条件},{指定列})
db.persons.find({},{_id:0,name:1,country:1})
db.persons.find({age:{$gte:27,$lte25}},{})
db.persons.find({country:{$in:[",USA","China"]}},{_id:0,name:1,m:1})
$or:[c:{$gt:85},{e:{$gt:90}}]
db.persons.find({sex:{$in:[null]}})
6.正则查询
db.persons.find({name:/li/i})
7. $not的使用
可以用到任何地方进行取反操作
db.persons.find({name:{$not:/li/i}})
$nin只能用在集合操作上
8.数组查询 $all
查询喜欢 JS 和 MONGODB 的信息
db.persons.find({books:{$all:["JS","MONGODB"]}},{_id:0,name:1,country:1})
查询第二本书是 JAVA 的信息
db.persons.find({"books.1":"JAVA"},{_id:0,name:1,country:1})
9.查询指定长度数组 $size 它不能参与比较
查询出喜欢的书箱数量有4本的学生
db.persons.find({books:{$size:4}}, {_id:0,name:1,country:1})
查询出喜欢的书箱数量大于3本的学生
1.增加字段size
db.persons.update({}, {$set:{size:4}},false,true)
2.改变书箱更新方式,每次增加书籍的时候size增加1
db.persons.update({查询器}, {$push:{books:"ORACLE"},$inc:{size:1}})
3.利用 $gt 查询
db.persons.find({size:{$gt:3}})
10.$slice 返回文档中指定数组的内部值
1.查询出 jim 的第2~4本书
db.persons.find({name:"jim"}, {books:{$slice:[1,3]}})
2.查询出最后一本书
11. $elemMatch
db.persons.find({school:{$elemMatch:{school:"K",score:"A"}}})
12. $where
查询年龄大于22岁,喜欢看C++书,在K学校上过学,
但是我们要尽量避免使用,
db.persons.find({"$where":function(){
var books = this.books;
var school = this.school;
if(this.age > 22){
for(var i = 0; i< books.length; i++){
if(books[i] == "C++"){
if(school){
for(var j = 0; j < school.length; j++){
if(school[j].school == "K"){
return true;
}
}
break;
}
}
}
}
}})
分页与排序
1.查询 persons 前5条
db.persons.find({}, {_id:0, name:1}).limit(5)
2.查询第5到10条,使用 sikp()
db.persons.find({}, {_id:0, name:1}).limit(5).skip(5)
3.sort 按年龄排序 (1是升序, -1是倒序)
db.persons.find({}, {_id:0, name:1}).sort({age:1});
注意:MongoDB的key可以是不同类型的数据,排序有优先级
最小值 > null > 数字 > 字符串 > 对象|文档 > 数组 > 二进制 > 对象ID > 布尔 > 日期 > 时间戳 > 正则 > 最大值
4.三条数据 一页进行分页
第一页-> db.persons.find({},{_id:0,name:1}).limit(3),skip(0);
第二页-> db.persons.find({},{_id:0,name:1}).limit(3),skip(3);
第一页-> db.persons.find({},{_id:0,name:1}).limit(pageSize),skip(pageIndex * PageSize);
5. skip有性能问题,一般情况下可以对数据进行另一种设计以实现分页
_id name age date
每次查询操作的时候后台传值把最后一个文档的日期保存下来
db.persons.find({date:{$gt:日期数值}}).limit(3)
游标和其他知识
1.
var persons = db.persons.find({name:"jim"})
while(persons.hasNext()){
obj = persons.next();
print(obj.books.length)
}
2.游标几个销毁的条件
1.客户端发来信息叫他销毁
2.游标迭代完成
3.默认游标超过10分钟没用
3.查询快照
快照后就会针对不变的集合进行游标操作了,看看使用方法
db.persons.find({$query:{name:"jim"},$snapshot:true})
高级查询选项
$query
$orderby
$maxscan:integer 最多扫描的文档数
$min: doc 查询开始
$max: doc 查询结束
$hint: doc 使用哪个索引
$explain:boolean 统计
$snapshot:boolean 一致快照
4.为什么用查询快照
如果不使用快照,游标读取到的数据可能是已经读取过的或跳过某些数据
#endregion 第三讲
#region 第四讲
索引详细
1.创建简单索引
var start = new Date();
for(var i=0; i<200000; i++){
db.books.insert({name:i, name:i+"book"})
}
var end = new Date();
end - start
var start = new Date();
db.books.find({number:72981})
var end = new Date();
end - start
//添加索引
db.books.ensureIndex({number:1})
2.索引使用需要注意
1.创建索引时,1是升序,-1是倒序
2.索引在提高查询性能的同时,会影响插入性能
3.索引要注意先后顺序
4.索引不是万能的,每个键建立索引不一定能提高性能
5.在做排序工作的时候,如果是越大数据量也可以考虑加上索引用来提高排序的性能
3.索引名称
1.用 MongoDBVUE 查看索引名称
2.创建索引同时指定索引的名字
db.books.ensureIndex({name:-1},{name:"book_name_index})
4.唯一索引
1.db.books.ensureIndex({name:-1}, {unique:true})
5.剔除重复的值, dropDups:true 时会自动删除重复的记录
db.books.ensureIndex({name:-1}, {unique:true}, {dropDups:true} )
6.查询时使用指定的索引
db.books.find({name:"IX_book_1", number:1}).hint({name:-1})
7. expain
1.如何详细查看本次查询使用了哪个索引和查询数据的状态信息
db.books.find({name:"12book"}).explain()
索引管理
1.system.indexes
db.system.indexes.find()
db.system.namespaces.find()
2.后台执行
执行创建索引的过程会暂时锁住表的问题如何解决 background:true
db.books.ensureIndex({number:1},{background:true})
3.删除索引
批量删除和精确删除
db.runCommand({dropIndexes:"books",index:"IX_books_name"})
db.runCommand({dropIndexes:"books",index:"*"})
空间索引
准备数据 map.js
添加2D索引 db.map.ensureIndex({"gis":"2d"}, {min:-1, max:201})
1.查询出距离点(70,180)最近的3个点
db.map.find({"gis":{$near:[70,180]}}, {gis:1, _id:0}).limit(3)
2.查询以点 (50,50)和点(190,190) 为对角线的正方形中所有点
db.map.find( {gis:{"$within":{$box:[[50,50],[190,190]]}}}, {_id:0:gis:1} )
3.(56,80)为圆心,50为半径
db.map.find( {gis:{$widthin:{$center:[[56,80],50]}}}, {_id:0,gis:1} )
#endregion 第四讲
#region 第五讲
count+distinct+group
1.count 查询美国学生的人数
db.persons.find({country:"USA"}).count()
2.distinct 查询一共有多少个国家,分别是什么
db.runCommand({distinct:"persons", key:"country"}).values
3.group
db.runCommand({group:{
ns:集合名称,
key:分组的键对象,
initial:初始化累加器,
$reduce:组分解器,
condition:条件,
finalize:组完成器
}})
1.查出 每个国家数学成绩最好的学生(成绩在90以上)
db.runCommand({group:{
ns:"persons",
key:{"country":true},
initial:{m:0},
$reduce:function(doc,prev){
if(doc.m > prev.m){
prev.m = doc.m;
prev.name = doc.name;
prev.country = doc.country;
}
},
condition:{m:{$gt:90}}
}})
2.在1的基础上,把每个人的信息连接起来放到 m 上
db.runCommand({group:{
ns:"persons",
key:{"country":true},
initial:{m:0},
$reduce:function(doc,prev){
if(doc.m > prev.m){
prev.m = doc.m;
prev.name = doc.name;
prev.country = doc.country;
}
},
condition:{m:{$gt:90}},
//完成器
finalize:function(prev){
prev.m = prev.name + " Math scores " + prev.m
}
}})
4.用函数格式化已经分组的键
db.persons.insert({counTry:"China", m:91,c:80,name:"wuwuwu"})
1.如果集合中出现键 count 和 counTry 同时存在,如何解决呢
$key:function(doc){
if(doc.counTry)return {country:doc.counTry}
else{
return {country:doc.country}
}
},
db.runCommand({group:{
ns:"persons",
key:{"country":true},
initial:{m:0},
$key:function(doc){
return {country : (doc.country ? doc.country : doc.counTry)}
},
$reduce:function(doc,prev){
if(doc.m > prev.m){
prev.m = doc.m;
prev.name = doc.name;
prev.country = doc.country?doc.country : doc.counTry
}
},
condition:{m:{$gt:90}},
//完成器
finalize:function(prev){
prev.m = prev.name + " Math scores " + prev.m
}
}})
数据库命令操作
1.命令执行器 runCommand
用命令执行完成一次删除表的操作
db.runcommand({drop:"map"})
2.如何查询mongodb提供了哪些命令
1.在 shell中执行 db.listCommands()
2.访问网址: http://localhost:28017/_commands
3.常用命令
1.查询服务器版本和主机操作系统
db.runCommand({buildInfo:1})
2.查询执行集合的详细信息,大小,空间,索引等
db.runCommand({collStats:"persons"})
3.查看操作本集合最后一次错误信息
db.runCommand({getLastError:"persons"})
固定集合特性
1.特性
1.固定集合默认是没有索引的,就算是 _id 也没有索引
2.由于不需要分配新的空间,插入速度也是非常快的
3.固定集合的顺序是确定的,导致查询速度也是非常快
4.最适合的应用就是日志管理
2.创建固定集合
1.创建一个新的固定集合,大小为100字节,可以存储文档10个
db.createCollection("mycoll", {size:100, capped:true, max:10})
2.把一个普通的集合变成固定集合
db.runCommand({convertToCapped:"persons", size:100000})
3.反向排序,默认是插入顺序排序
db.mycoll.find().sort({$natural:-1})
4.尾部游标, shell 不支持, java和 php等驱动支持
只能用到固定集合上面,没有结果的时候,不会自动销毁,它会一直等待结果的到来
GridFS文件系统
1.概念 GridFS 是 MongoDB 自带的文件系统是二进制
大型文件系统的绝大多数用GridFS
2.利用工具
mongofiles.exe
3.使用 GridFS
1.查看 GridFS 的所有功能
cmd->mongofiles
2.上传一个文件
mongofiles -d foobar -l "E:\a.txt" put "a.txt"
3.用 mongoVUE查看,在 shell 中无法查看
mongofiles -d foobar get "a.txt"
3.查看所有文件
mongofiles -d foobar list
4.删除已经存在的文件
mongofiles -d foobar delete ‘a.txt‘
补充->服务器端脚本
1.服务器端运行eval
db.eval("function(name){return name}", "wujialong")
2.在服务器上保存js变量,共全局调用
1.把变量加载到 system.js 中
db.system.js.insert({_id:"name",value:"wujialong"})
db.system.js.insert({_id:"showName",value:function(){return name}})
2.调用
db.eval
#endregion 第五讲
#region 第六讲
mongoDB启动配置
1.启动项 mongod -help
--dbpath 默认是 c:\data\db
--port 默认是 27017
--fork
--config 指定配置文件的路径
--auth 用安全认证的方式启动数据库,默认不启用
mongod.exe --config mongodb.conf
2.停止服务
1. ctrl+c
2.use admin
db.shutdownServer()
导出/导入,运行时备份
导出
-host 哪台机器
-port 哪个端口
-d 数据库
-c 集合
-o 文件名
CMD命令, mongoexport -d foobar -c persons -o c:\persons.js
导入
-db 数据库
mongoimport -db foobar -collection persons -file c:\persons.js
备份
1.运行时备份 mongodump
API http:cn.docs.mongodb.org/manual/reference/mongodump
mongodump -host 127.0.0.1:27017 -d foobar -o d:/foobar
2.运行时恢复 mongorestore
API http:cn.docs.mongodb.org/manual/reference/mongorestore
mongorestore -host 127.0.0.1:27017 -d foobar -directoryperdb d:/foobar/foobar
3.直接复制文件
fsync锁,数据修复
上锁可以让缓冲池的数据全部保存到数据库,这在数据库备份的时候很有用
上锁: db.runCommand({fsync:1,lock:1})
解锁: db.currentOp()
数据修复:当停电等不可逆转灾难时,由于 mongodb 的存储结构导致会产生垃圾数据,在数据恢复以后这些垃圾数据依然存在,这时数据库提供一个自我修复的能力,使用起来很简单
db.repairDatabase()
用户管理,安全认证
1.添加用户
//添加用户
use admin
db.addUser("wujialong", "123")
use foobar
db.addUser("wujialongcn", "123")
//切换登录用户
db.auth("wujialong", "123")
//删除用户
db.sytem.users.remove({user:"wujialong"})
#endregion 第六讲
#region 第七讲
主从复制
1.
--master 设置为主数据库
--slave 设置为从数据库
--source 设置谁是主数据库
--only 从节点 指定复制某个数据库,默认是复制全部数据库
--slavedelay 从节点 设置主数据库同步数据的延迟时间(单位:秒)
--fastsync 从节点以主数据库的节点快照为节点启动从数据库
--autoresync 从节点数据与主数据库不同步,则重新同步数据库. 如:从数据库下线20天,当从节点重新上线后,会自动同步这20天的数据到从节点
--oplogsize 主节点上 oplog的大小,越大的话,当从节点下线一段时间后重新上线时可以同步的数据越多
在启动的时候,可以只有1个主数据库,0个从数据库.从数据库可以在运行时动态添加
2.
主数据库config内容
dbpath = C:\master_slave\8888 #主数据库地址
port = 8888 #主数据库端口号
bing_ip = 127.0.0.1 #主数据库所在服务器
master = true #设置为主数据库
从数据库config内容
dbpath = C:\master_slave\7777 #从数据库地址
port = 7777
bind_ip = 127.0.0.1 #从数据库所在服务器
source = 127.0.0.1:8888 #主数据库地址
slave = true #设置为从数据库
3.利用 shell 动态添加和删除从节点
在从节点中有 db.sources, 保存的是主节点信息,在配置的时候不设置 --source 参数,可以在shell中通过insert来动态配置
db.sources.insert({"host":"127.0.0.1:8888"})
db.sources.remove({"host":"127.0.0.1:8888"})
副本集
警告:
1.只能在主节点上进行查询.
2.备份节点不能进行查询操作.
可以打开shell,查看提示信息的方式确定哪个是主节点
1.设置
A.
dbpath = C:\replset\A
port = 1111
bing_ip = 127.0.0.1
replSet = child/127.0.0.1:2222 #设置下一个同伴
B.
dbpath = C:\replset\B
port = 2222
bing_ip = 127.0.0.1
replSet = child/127.0.0.1:3333 #设置下一个同伴
C.
dbpath = C:\replset\C
port = 3333
bing_ip = 127.0.0.1
replSet = child/127.0.0.1:1111 #设置下一个同伴
2.连接副本集中任意一个,执行初始化操作
use admin
db.runCommand({"replSetInitiate":{
"_id":"child",
"members":[
{ "_id":1,
"host":"127.0.0.1:1111"
},
{ "_id":2,
"host":"127.0.0.1:2222"
},
{ "_id":3,
"host":"127.0.0.1:3333"
}
]
}})
3.查看副本集状态(只能在主节点中查询)
rs.status()
4.节点和初始高级参数
standard 常规节点,可以参与投票,有可能成为活跃节点
passive 副本节点,参与投票,但不会成为活跃节点
arbiter 仲裁节点,只参与投票,不复制也不成为活跃节点
5.高级级数
priority 0~1000 之间, 0代表是副本节点, 1到1000是常规节点
arbiterOnly:true 仲裁节点
用法:
"members":[
{ "_id":1,
"host":"127.0.0.1:1111",
arbiterOnly:true
}
]
6.优先级相同的时候,仲裁的规则
7.读写分离操作(扩展读)
一般情况下,副本节点是不能进行数据库读操作的
但是在读取密集型的系统中进行读写分离是十分必要的
设置: slaveOkey : true 主服务器进行写操作,从服务器进行读操作
slaveOkey 在shell 中无法使用,在java等高级语言中有
8. --master --oplogSize 字节
在主数据库中设置同步日志保存的大小
use local
db.oplog.rs
#endregion 第七讲
#region 第八讲
分片 插入负载技术
3.什么时候用到分片
1.机器的磁盘空间不足
2.单个服务器已经不能满足大量的插入操作
3.想把大数据放到内存中提高性能
4.分片步骤
1.创建一个配置服务器
config.conf:
dbpath = config
port = 2000
bind_ip = 127.0.0.1
mongod --config config.conf
2.创建路由服务器,并且连接配置服务器
路由器调用 mongos 命令:
mongos --port 1000 --configdb 127.0.0.1:2000
3.添加两个分片数据库
8081和8082
4.利用路由为集群添加分片(允许本地访问)
db.runCommand({addshard:"127.0.0.1:8081", allowLocal:true})
db.runCommand({addshard:"127.0.0.1:8082", allowLocal:true})
警告:在进行这些操作之前,不能使用任何数据库语句
5.启用数据库分片,
db.runCommand({"enablesharding" : "foobar"})
6.对集合进行分片
db.runCommand({ "shardcolleciton", "foobar.bar", "key":{"_id":1} })
7.使用大数据量进行测试
8.查看配置库于分片服务器的配置存储
db.printShardingStatus()
9.查看集群对bar的自动分片机制配置信息
mongs> use config
mongos> db.shards.find()
#endregion 第八讲
#endregion 第八讲