mongodb学习笔记
A.
Mongodb特点、功能、使用场景
Mongodb的安装和配置
Mongodb体系结构
数据库的启动、停止、连接
JSON/BSON数据格式
Mongodb
1. 特点
数据在内存中,通过后台线程写入磁盘
无模式结构进行数据存储---->如产品数据,不同的产品描述完全不一样,那么如果用关系数据库很难处理
可以进行实时插入(写性能非常好)
自动碎片处理
存储数据格式是二进制json格式===>bson
支持二进制数据和大型对象(图片)
2.使用场景
网站数据 Mongodb 非常适合实时的插入,更新、查询,并且具备了网站实时数据存储所需要的复制及高度伸缩性
缓存:作用信息数据的缓存层
大尺寸,低价值的数据
高伸缩性,适合百台服务器组成的数据库集群有,MapReduce引擎的内置支持。
3. 不适用场景
.高度事务性的系统 例如银行、会计
传统的商业智能应用
无法控制数据写入磁盘的顺序
4.Mongodb 的安装
windows版: 解压、进入bin目录(如果设置了环境变量无所谓那个目录了)
在mongodb目录下建立data文件夹,指定存放数据的目录--->可以是其它目录
启动命令 mongod --dbpath=d:\mongodb\data
客户端连接:mongo
Linux版:
tar -zxvf mongodb-linux-i686-2.6.3.tgz
建立日志、数据文件夹
启动命令:./mongod -dbpath=/usr/nosqlsoft/mongodb/db -logpath=/usr/nosqlsoft/mongodb/logs/mongo.log --fork
客户端连接: ./mongo
Mongodb启动可以有一些其它参数
dbpath
logpath 错误日志文件
logappend 错误日志采用的追加模式
bind_ip 对外服务绑定的ip,一般设置为空
port 对外服务的端口(不想用默认的)
fork 以后台以守护进行的方式运行服务
MaxConns
其它... ....
5.体系结构
Mongodb 是一个可移植的数据库,在不同平台是完全一样的,数据的逻辑结构和数据存储方式等等。
关系数据库是数据库的概念database Mongodb中是db的概念
关系数据库 -->表 Mongodb--->Collection(集合)
关系数据库 --->记录 Mongodb --->document(文档)
数据存储结构
如果有数据库foo 数据库文件就会有foo.ns,foo.0,foo.1,foo.2等等
Mongodb有预分配空间的机制,每个预分配文件都用0进填充
Mongodb就始终保持额外的空间和空余的数据文件,避免数据暴增长带来的磁盘压力写过大的问题
数据文件每新分配一次,它的大小都会是上一个数据文件大小的2倍。最大2G
数据库每张表(集合)对应一个命名空间,这写数据都集中在.ns文件中
6. 数据格式 二进制json ====》bson格式
{"300001":{name:"上证指数",yes:3000.0,tod:2990.1,now:3002.73},"000001":{name:"浦发银行",yes:23.22,tod:23.5,now:23.0}}
json格式类型执行非常快,且不昂贵
对js来说表示的对象
可以跨域传递信息
-------------------------------------------------------------------------------------------------------------
B.
bson
Mongodb的增删改查操作
Mongodb 客户端GUI工具
Mongodb基本操作
1.bson 二进制的json
2.基本操作
关闭服务 :可以直接ctrl+c关闭
也可以是进入admin数据库 use admin
db.shutdownServer()
2.1插入记录的操作
j = {name:"zhangsan",age:30};
db.mydb.save(j)
t = {name:"lisi",age:32};
db.mydb.insert(j)
注意:不需要预先创建一个集合,在第一次插入数据时会自动创建。
文档中可以存储任何结构的数据,实际应用中大部分还是相同文档的集合,这个比较灵活,结构不同也没关系
每次插入数据的时候集合中都会有一个ID,属性名称是_id
写一个循环插入数据:
for(var i = 1; i < 10;i++)db.mydb.save({x:3,j:i})
db.mydb.find()
如果屏幕没有全部显示可以使用it命令显示下一屏
2.2"_id"
存储在Mongodb中的每一个文档都会有一个默认主键_id,名称固定
可以是任何类型,默认是ObjectId ,必须唯一
如果不用这个类型,必须显示写出 db.mydb.insert({"_id":"0001",name:"zhangsan"})
2.3查询操作
db.mydb.find()
var cursor = db.mydb.find();
while(cursor.hasNext()) printjson(cursor.next())
===============================
类似与js 脚本
db.mydb.find().forEach(printjson);
================
在Mongodb的脚本当中
var cursor = db.mydb.find()
可以把cursor当做一个数组来操作
printjson(cursor[0])
printjson(cursor[1]);
======================
var arr = db.mydb.find().toArray();
arr[0];
arr[1];
注意:这些特性只是在Mongodb shell里使用,而不是所有其它应用程序都支持。
Mongodb 游标对象不是没有快照,如果有其他用户在集合里第一次后者最后一次调用next(),你可能得不到游标里的数据,所以要明确锁定你查询的游标
2.4 简单的条件查询
db.mydb.find({x:4}).forEach(printjson)
db.mydb.find({x:4,j:90}).forEach(printjson);
2.5 findOne()语法
只返回游标中的第一条数据,或者返回null即是空数据
printjson(db.mydb.findOne({x:4}));
printjson(db.mydb.findOne({x:1000}));1000不存在返回null
2.6通过limit限制结果集的数量
db.mydb.find().limit(3);
2.7修改记录
db.mydb.update({name:"zhangsan"},{$set:{name:"zhangsan_new"}})
db.mydb.update({属性1:"值",属性2:"值"...},{$set:{属性:新值,属性:新值}})
3.常用的工具集
bsondump:讲bson格式的文件转存为json格式数据
mongo:客户端命令行工具,其实也是一个js解释器,支持js语法
mongod:数据库服务器
mongodump/mongorestore 数据库备份和回复工具
mongoexport/mongoimport 数据导入导出工具
mongofiles:GridFs管理工具,实现二进制文件的存取
mongos:分片路由,如果使用sharding功能,应用程序连接的是mongos而不是mongod
mongostat:实时性能监控工具
4.客户端GUI
MongoVUE http://www.mongovue.com 可视化工具
PHP写的工具 RockMongo http://code.google.com/p/rock-php/
MongoHub 专门针对Mac系统的图形管理界面
-------------------------------------------------------------------------------------------------------------------------------
C.
Mongodb 高级查询
1.条件操作符
< ,<=,>,>=
db.collection.find({"field":{$gt:value}})//大于
db.mydb.find({"age":{$gt:30}});
db.collection.find({"field":{$lt:value}})//小于
db.collection.find({"field":{$gte:value}})//大于等于
db.collection.find({"field":{$lte:value}})//小于等于
多条件
db.collection.find({"field1":{$gt:value1,$lt:value2}})
db.mydb.find({"age":{$gte:30,$lte:32}});
db.mydb.find({"age":{$gte:30,$lte:32},"name":"lisi"});
2.$all 匹配所有
这个操作符合sql语法的in类似,不同的是,in只需要满足()中的某个即可,
而$all必须满足[]内的所有值:
db.mydb.insert({name:"zhaoliu",age:[30,32,34]});
db.mydb.find({"age":{$all:[30,32]}});
3.$exists 判断字段是否存在
查询含有age属性的文档
db.mydb.find({age:{$exists:true}})
查询不含有age属性的文档
db.mydb.find({age:{$exists:false}})
4.NULL值处理
db.mydb.find({"age":{$in:[null],$exists:true}}); 查询含有age属性,并且值是null的
查询的是没有age属性和有age属性值为null的文档
db.mydb.find({"age":{$in:[null]}});
5.$mod取模运算
age属性除以10余数是2的文档取出
db.mydb.find({age:{$mod:[10,2]}}); age属性%10 ==2的
6.$ne 不等于
年龄不是30的,全部查询出来 包含了不含age属性的文档,也包含了age属性是null的文档
db.mydb.find({age:{$ne:30}})
查询有年龄属性并且值不是30的。
db.mydb.find({age:{$ne:30,$exists:true}});
7.$in 与sql标准语法的用途是一样的,即要查询的是一系列枚举范围内.
db.mydb.find({age:{$in:[30,23]}})
8.$nin 不包含
db.mydb.find({age:{$nin:[30,23]}})
db.mydb.find({age:{$nin:[30,23],$exists:true}})
9.$size 数组元素的个数
db.mydb.find({age:{$size:3}})
db.mydb.find({age:{$size:1}})
db.mydb.insert({age:[100]});
db.mydb.find({age:{$size:1}})
10.正则表达式匹配
查询不匹配name=z*带头的记录
db.mydb.find({name:{$not:/^z.*/}})
db.mydb.find({name:{$not:/^z.*/,$exists:true}});
11.JavaScript查询和$where查询
查询j 大于20的数据
db.mydb.find({j:{$gt:20}})
db.mydb.find({$where:"this.j>20"});
db.mydb.find("this.j>20")
=======================
f=function(){return this.j>20;}
db.mydb.find(f);
12.count查询记录条数
db.mydb.find().count()
db.mydb.find({j:{$gt:90}}).count()
13.skip限制返回文档的起点
从第3条记录开始,返回5条记录
db.mydb.find().skip(3).limit(5);
14.sort
db.mydb.find({age:{$exists:true}}).sort({age:1})升序
db.mydb.find({j:{$exists:true}}).sort({j:-1});
----------------------------------------------------------------------------------
D:
mongodb高级应用
存储过程
capped Collection使用
GridFs实现海量数据存储
Mongodb的MapReduce实现
1.游标
1>
for(var a=db.person.find();a.hasNext();){
printjson(a.next());
}
2>
var a = db.person.find();
while(a.hasNext()){
printjson(a.next());
}
3>
db.person.find().forEach(function(u){ printjson(u)});
2.存储过程
mongodb的存储过程利用javascript书写
sql自定义函数
function addNumbers(x,y){
return x+y;
}
sql自定义函数转换成存储过程db.system.js.save();
1)定义存储过程
db.system.js.save({"_id":"addNumbers",value:function(x,y){ return x+y;}});
--->_id:对应相当有函数名 value:对应函数体
这样形成了mongodb的存储过程
2)查看存储过程:
db.system.js.find();
3)执行存储过程
db.eval('语句');
如:
db.eval('addNumbers(2,3)');
注意:eval()是个特殊函数,可以不定义存储过程,直接内部嵌套函数使用
db.eval(function(){ return 3+3;});
-----------------------------------------------------
db.system.js.save({"_id":"getCount",value:function(){ return db.person.count();}});
调用
db.eval('getCount()');
注意:js的语法与mongodb的基本操作
3.capped collection
性能比较出色
1)-种特殊集合,固定大小的集合,数据满了后按lru(最近最少使用)和按着插入顺序对老化数据移除
2)建立是预先指定大小,数据满后,再增加数据,将最老数据替换掉
3)可以插入和更新,不能查过集合的大小否则更新失败
4)不可以删除,可以通过drop删除集合中所有行,删除后,集合需要重建
5)32位机器上,一个capped collection最大为483.5m
64位机器上无限制
****用途
(1)loggging 做日志,将系统日志写入, 可以减少人员维护(自动清理lru),同时capped collection可以查看最近的插入数据(自动维护查询顺序),capped collection有最大容量限制
(2)cached
(3)auto archiving 将统计的中间结果记录到capped collection中,便于统计提取
发挥最大性能
利用写入特性,写入多,读取少,最少不要建立索引,否则影响插入速度
利用自然排序也就是维护插入顺序
使用时候注意事项
建立时候设定maxsize,和 初始size,因为capped collection使用时候,总是先检查size再检查max
可以利用validate查看使用了多少,以便决定设定多大
创建cappped collection语法
db.createCollection("capcol",{cappped:true,size:100000,max:100});
创建普通:collection
db.createCollection("mu");
删除集合中的元素
db.collectionName.drop();
注意:
默认情况下系统会自动为collection创建索引,但是不会对capped collection创建索引
4.GridFs
是mongodb的一种存储大型文件的规范
内部提供了将大型文件进行存储,将文件分成若干个小块(小文档进行存储)
可以存放图片或视频文件
注意:在互联网中一般用针对性的分布式文件系统存放文件、视频等hdfs gfs tfs
GridFs存放和查看文件
GridFs利用两个集合存放文件,默认前缀为fs
即
1)files 存放元数据对象
2)chunks存放相关系统二进制块
fs.files fs.chunks
命令
mongodbfiles put d:\\filename
mongodbfiles list
db.fs.files.find();
如
mongofiles put d:\\ddd.pdf
mongofiles list
获取文件
mongofile get filename
如
mongofiles get d:\\ddd.pdf
客户端查看:
show collections;
可以显示 fs.chunks,fs.files
db.fs.files.find();查看字段说明
filename:文件存放名称
chunkSize:分块大小
uploadDate:入库时间
md5:加密方式
connected to: 127.0.0.1
added file: { _id: ObjectId('54f48b837ea57845ede86935'), filename: "d:\\ddd.pdf"
, chunkSize: 261120, uploadDate: new Date(1425312644357), md5: "21c7b1d4d246f779
20f45f5ed855f23c", length: 49307054 }
============================================
E:Mongodb管理
1.MapReduce
很像关系数据库中的分组操作
Mongodb使用Map/Reduce进行并行统计
Mongodb使用MapReduce需要使用两个函数,一个Map函数还有一个就是Reduce函数。
Map函数是通过调用emit(key,value)遍历collection中所有记录,然后将key与value传递
给Reduce函数进行处理。这两个函数都可以使用JS实现
通过db.runCommand或者是mapReduce命令来执行一个操作
map函数----->分解产生key values
reduce函数--->合并接受key values参数进行操作
a.准备数据
db.students.insert({classid:1,age:14,name:"Tom"});
db.students.insert({classid:1,age:14,name:"Tom"});
db.students.insert({classid:1,age:14,name:"Tom"});
db.students.insert({classid:2,age:9,name:"Tony"});
db.students.insert({classid:2,age:13,name:"Harry"});
db.students.insert({classid:2,age:19,name:"Vincent"});
db.students.insert({classid:1,age:14,name:"Bill"});
db.students.insert({classid:2,age:17,name:"Bruce"});
b.map函数
//相当于this.classid的值作为key,1作为对象的values
m = function(){emit(this.classid,1)};
c.reduce函数
r = function(key,values){
var x = 0;
values.forEach(function(v){x+=v});
return x;
}
d.执行
res = db.runCommand({
mapreduce:"students",
map:m,
reduce:r,
out:"students_res"
});
以此作为进一步处理的函数
f = function(key,value){return {classid:key,count:value};}
res = db.runCommand({
mapreduce:"students",
map:m,
reduce:r,
out:"students_res",
finalize:f
});
加入一些条件
res = db.runCommand({
mapreduce:"students",
map:m,
reduce:r,
out:"students_res",
finalize:f,
query:{age:{$lt:10}}});
另外一个案例
book1 = {name:"Understanding Java",pages:100};
book2 = {name:"Understanding Json",pages:200};
book3 = {name:"Understanding XML",pages:300};
book= {name:"Understanding webService",pages:400};
book={name:"Understanding Axis2",pages:150};
map函数
var map = function(){
if(this.pages>=250)
category = "Big Books";
else
category = "Small Books";
emit(category,this.name);
};
var reduce = function(key,values){
var sum = 0;
values.forEach(function(doc){
sum += 1;
});
return {books:sum};
};
执行
db.books.mapReduce(map,reduce,{out:"book_results"});
查看db.book_results.find();
2. 数据导出mongoexport
mongoexport -d test -c books -o d:\\books.dat ---->json格式
-d 指定数据库 -c 集合 -o 文件
mongoexport -d test -c books -csv -o d:\\books_csv.dat ---->csv格式
3.导入
mongoimport -d test -c books d:\\books.dat --->json格式
mongoimport -d test -c books --type csv --headerline --file d:\\books_csv.dat--->导入csv格式数据
------------------------------------------------------------------------------------------
f.
osql第十八讲-Mongodb服务器管理
1.备份与恢复
如何创建一个数据库 use 数据库名称 如果数据库存在直接打开,如果不存在创建并打开
use testdb
备份 mongodump -d 数据库
mongodump -d testdb
会直接在当前目录下创建已给dump目录,用于存放备份出来的文件
可以指定备份存放的目录
mongodump -d testdb -o mydump
恢复
删除数据库 进入数据库 use 数据库名 db.dropDatabase();
mongorestore -d 数据库名称 dump/数据库名称
mongorestore -d testdb dump/testdb
mongorestore -d testdb 自定义文件夹的名字/testdb
可以不用先删除数据库用的时候指定-drop 参数即可 先删除表再向表中插入数据
mongorestore -d testdb -drop dump/testdb
2.访问控制
前面Mongodb启动后,都可以直接操作,而且是任意操作。这样会带来不安全。
我们可以:
绑定IP内网地址访问mongodb服务
设置监听端口
使用用户名和口令
绑定IP
启动的时候添加参数 --bind_ip
如:启动时添加参数 --bind 192.168.0.3 --->只能该ip访问
mongod --bind_ip 127.0.0.1 --dbpath=d:\mongodb\data就只能本机访问了。
设定端口默认端口是27017
mongod --bind_ip 127.0.0.1 --port 28018 --dbpath=d:\mongodb\data
mongo 127.0.0.1:28018
用户名和密码
默认对所有的库具有root权限,所有操作都可以进行。
可以通过指定参数来设置。
只需要启动--auth --->启动了登陆验证模块 默认启动之后操作都还可以进行。
在最初的时候Mongodb都默认有一个admin数据库(是空的)
admin.system.users中保存了比其它数据库中设置的用户权限更大的信息。
当admin.system.users中没有添加任何用户时,即使Mongodb启动了验证
模块依然可以进行任何操作。所以需要往该集合中增加文档。
建立系统root用户
db.addUser("root","1234");
db.auth("root","1234");
mongo -u root -p
输入密码1234
连接成功
以后启动时,如果加了--auth 连接时必须通过用户名密码,否则能连接,不能进行其他操作
Mongodb也支持为某个特定的数据库来设置用户。
给test加个只读用户
db.addUser("用户名","密码",true)
用该用户登录 能进行只读操作
3.命令操作
db.user.count();
mongo test --eval "printjson(db.user.count())"