MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
G:
md \data\db
启动mongod,指定数据文件路径
mongod --dbpath G:\MongoDB\db
启动mongod,指定配置文件(自己编写)
mongod --config G:\MongoDB\MongoDB.conf
启动mongo客户端
mongo
基本配置
| 选项 | 功能 |
|---|---|
| --quiet | # 安静输出 |
| --port arg | # 指定服务端口号,默认端口27017 |
| --bind_ip arg | # 绑定服务IP,若绑定127.0.0.1,则只能本机访问,不指定默认本地所有IP |
| --logpath arg | # 指定MongoDB日志文件,注意是指定文件不是目录 |
| --logappend | # 使用追加的方式写日志 |
| --pidfilepath arg | # PID File 的完整路径,如果没有设置,则没有PID文件 |
| --keyFile arg | # 集群的私钥的完整路径,只对于Replica Set 架构有效 |
| --unixSocketPrefix arg | # UNIX域套接字替代目录,(默认为 /tmp) |
| --fork | # 以守护进程的方式运行MongoDB,创建服务器进程 |
| --auth | # 启用验证 |
| --cpu | # 定期显示CPU的CPU利用率和iowait |
| --dbpath arg | # 指定数据库路径 |
| --diaglog arg | # diaglog选项 0=off 1=W 2=R 3=both 7=W+some reads |
| --directoryperdb | # 设置每个数据库将被保存在一个单独的目录 |
| --journal | # 启用日志选项,MongoDB的数据操作将会写入到journal文件夹的文件里 |
| --journalOptions arg | # 启用日志诊断选项 |
| --ipv6 | # 启用IPv6选项 |
| --jsonp | # 允许JSONP形式通过HTTP访问(有安全影响) |
| --maxConns arg | # 最大同时连接数 默认2000 |
| --noauth | # 不启用验证 |
| --nohttpinterface | # 关闭http接口,默认关闭27018端口访问 |
| --noprealloc | # 禁用数据文件预分配(往往影响性能) |
| --noscripting | # 禁用脚本引擎 |
| --notablescan | # 不允许表扫描 |
| --nounixsocket | # 禁用Unix套接字监听 |
| --nssize arg (=16) | # 设置信数据库.ns文件大小(MB) |
| --objcheck | # 在收到客户数据,检查的有效性, |
| --profile arg | # 档案参数 0=off 1=slow, 2=all |
| --quota | # 限制每个数据库的文件数,设置默认为8 |
| --quotaFiles arg | # number of files allower per db, requires --quota |
| --rest | # 开启简单的rest API |
| --repair | # 修复所有数据库run repair on all dbs |
| --repairpath arg | # 修复库生成的文件的目录,默认为目录名称dbpath |
| --slowms arg (=100) | # value of slow for profile and console log |
| --smallfiles | # 使用较小的默认文件 |
| --syncdelay arg (=60) | # 数据写入磁盘的时间秒数(0=never,不推荐) |
| --sysinfo | # 打印一些诊断系统信息 |
| --upgrade | # 如果需要升级数据库 |
Replicaton 参数
| 选项 | 功能 |
|---|---|
| --fastsync | # 从一个dbpath里启用从库复制服务,该dbpath的数据库是主库的快照,可用于快速启用同步 |
| --autoresync | # 如果从库与主库同步数据差得多,自动重新同步, |
| --oplogSize arg | # 设置oplog的大小(MB) |
主/从参数
| 选项 | 功能 |
|---|---|
| --master | # 主库模式 |
| --slave | # 从库模式 |
| --source arg | # 从库 端口号 |
| --only arg | # 指定单一的数据库复制 |
| --slavedelay arg | # 设置从库同步主库的延迟时间 |
Replica set(副本集)选项:
| 选项 | 功能 |
|---|---|
| --replSet arg | # 设置副本集名称 |
Sharding(分片)选项
| 选项 | 功能 |
|---|---|
| --configsvr | # 声明这是一个集群的config服务,默认端口27019,默认目录/data/configdb |
| --shardsvr | # 声明这是一个集群的分片,默认端口27018 |
| --noMoveParanoia | # 关闭偏执为moveChunk数据保存 |
上述参数都可以写入 mongod.conf 配置文档里例如:
dbpath = /data/mongodb
logpath = /data/mongodb/mongodb.log
logappend = true
port = 27017
fork = true
auth = true
也可以当启动参数,如:
./mongod -shardsvr -replSet shard1 -port 16161 -dbpath /data/mongodb/data/shard1a -oplogSize 100 -logpath /data/mongodb/logs/shard1a.log -logappend -fork -rest
1. #进入数据库admin
use admin
// use <db> 命令可以用于创建数据库,db.<db>.insert({"name":"菜鸟教程"})之后才会真正创建数据库
2. #增加或修改用户密码
//db.addUser('name','pwd') #V3版本mongoDB已经不再使用addUser,而是采用了db.createUser
db.createUser(
{
user: "name",
pwd: "pwd",
roles: [ "readWrite", "dbAdmin" ]
}
)
3. #查看用户列表
db.system.users.find()
4. #用户认证
db.auth('name','pwd')
这一个返回1就认证成功了,只有认证成功才能对数据库进行操作
5. #删除用户
//db.removeUser('name') #已过时
db.dropUser('accountUser')
6. #查看所有用户
show users
7. #查看所有数据库
show dbs
7.查看当前数据库
db
8. #查看所有的collection
show collections
9. #查看各collection的状态
db.printCollectionStats()
10. #查看主从复制状态
db.printReplicationInfo()
show dbs 显示数据库列表
use dbname 进入dbname数据库,大小写敏感,没有这个数据库也不要紧
show collections 显示数据库中的集合,相当于表格
db.users.save({"name":"lecaf"}) 创建了名为users的集合,并新增了一条{"name":"lecaf"}的数据
db.users.insert({"name":"ghost", "age":10}) 在users集合中插入一条新数据,,如果没有users这个集合,mongodb会自动创建
save()和insert()也存在着些许区别:若新增的数据主键已经存在,insert()会不做操作并提示错误,而save() 则更改原来的内容为新内容。
存在数据:{ _id : 1, " name " : " n1 "} ,_id是主键
insert({ _id : 1, " name " : " n2 " }) 会提示错误
save({ _id : 1, " name " : " n2 " }) 会把 n1 改为 n2 ,有update的作用。
db.users.remove() 删除users集合下所有数据
db.users.remove({"name": "lecaf"}) 删除users集合下name=lecaf的数据
db.users.drop()或db.runCommand({"drop","users"}) 删除集合users
db.runCommand({"dropDatabase": 1}) 删除当前数据库
db.dropDatabase() 删除当前数据库
db.users.find() 查找users集合中所有数据
db.users.findOne() 查找users集合中的第一条数据
db.users.update({"name":"lecaf"}, {"age":10}) 修改name=lecaf的数据为age=10,第一个参数是查找条件,第二个参数是修改内容,除了主键,其他内容会被第二个参数的内容替换,主键不能修改
db.collection.find({ "key" : value }) 查找key=value的数据
db.collection.find({ "key" : { $gt: value } }) key > value
db.collection.find({ "key" : { $lt: value } }) key < value
db.collection.find({ "key" : { $gte: value } }) key >= value
db.collection.find({ "key" : { $lte: value } }) key <= value
db.collection.find({ "key" : { $gt: value1 , $lt: value2 } }) value1 < key <value2
db.collection.find({ "key" : { $ne: value } }) key <> value
db.collection.find({ "key" : { $mod : [ 10 , 1 ] } }) 取模运算,条件相当于key % 10 == 1 即key除以10余数为1的
db.collection.find({ "key" : { $nin: [ 1, 2, 3 ] } }) 不属于,条件相当于key的值不属于[ 1, 2, 3 ]中任何一个
db.collection.find({ "key" : { $in: [ 1, 2, 3 ] } }) 属于,条件相当于key等于[ 1, 2, 3 ]中任何一个
db.collection.find({ "key" : { $size: 1 } }) $size 数量、尺寸,条件相当于key的值的数量是1(key必须是数组,一个值的情况不能算是数量为1的数组)
db.collection.find({ "key" : { $exists : true|false } }) $exists 字段存在,true返回存在字段key的数据,false返回不存在字度key的数据
db.collection.find({ "key": /^val.*val$/i }) 正则,类似like;“i”忽略大小写,“m”支持多行
db.collection.find({ $or : [{a : 1}, {b : 2} ] }) $or或 (注意:MongoDB 1.5.3后版本可用),符合条件a=1的或者符合条件b=2的数据都会查询出来
db.collection.find({ "key": value , $or : [{ a : 1 } , { b : 2 }] }) 符合条件key=value ,同时符合其他两个条件中任意一个的数据
db.collection.find({ "key.subkey" :value }) 内嵌对象中的值匹配,注意:"key.subkey"必须加引号
db.collection.find({ "key": { $not : /^val.*val$/i } }) 这是一个与其他查询条件组合使用的操作符,不会单独使用。上述查询条件得到的结果集加上$not之后就能获得相反的集合。
指定返回那些列(键):
db.users.find({}, {‘name’ : 1, ‘skills’ : 1});
补充说明: 第一个{} 放where条件 第二个{} 指定那些列显示和不显示 (0表示不显示 1表示显示)
_id默认设置是1,所有也返回回来,可以设置_id不返回,例子:
>db.orders.find({},{"onumber":1,"cname":1,"_id":0})
db.collection.find().sort({ "key1" : -1 ,"key2" : 1 }) 这里的1代表升序,-1代表降序
db.collection.find().limit(5) 控制返回结果数量,如果参数是0,则当作没有约束,limit()将不起作用
db.collection.find().skip(5) 控制返回结果跳过多少数量,如果参数是0,则当作没有约束,skip()将不起作用,或者说跳过了0条
db.collection.find().skip(5).limit(5) 可用来做分页,跳过5条数据再取5条数据
db.collection.find().count(true) count()返回结果集的条数
db.collection.find().skip(5).limit(5).count(true) 在加入skip()和limit()这两个操作时,要获得实际返回的结果数,需要一个参数true,否则返回的是符合查询条件的结果总数
源数据
{ "uuid" : 12700004, "card" : 981.3000000000029,
"weixin" : {
"unionId" : "o1wS90l6kHDFXY2lAPDb9bPxRZxI1",
"openId" : "o9zCJ1Aat93B0UjdlCFDAWmimBcEb",
"nick" : "麦袋",
"sex" : 1,
"avatar" : "http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoNcMa5gLGs9iaTYCmNqycSk5XUWzKDVfj6sPkk1Oia0YSy3SmMrcX3kxsvEu4UfiblckRo7CpM0xicKg/1321"
},
"liaobe" : null,
"mobile" : {
"number" : "18874819762"
},
"visitor" : null,
"accountType" : 1,
"mobileRewardReceived" : true
}
MongoDB 查询数据的语法格式如下:
db.collection.find(query, projection)
query :可选,使用查询操作符指定查询条件
projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)
db["user"].find() # MongoDB写法
db["user"].find().pretty() # 是find出的数据在命令行中更加美观显示,不至于太紧凑,同select * from user\G;
select * from user;
db["user"].find({},{"liaobe":1,"mobile":1}).pretty() # 如果projection不为空,不需要查询条件时,必须键入{} # projection 指定哪些列显示和不显示 (0:不显示 1:显示)
select liaobe,mobile from user\G;
"mobile" : {
"number" : "18874819762"
},
以上数据,要查询number=18874819762的数据
db["user"].find({"mobile.number":"18874819762"}).pretty() # 一级.二级.三级,依次类推
db["user"].find({"accountType" : 1}).pretty()
select * from user where accountType=1\G;
db["user"].find({"uuid" : 12700004,"accountType" : 1,"authType" : 2}).pretty() # 多个条件用, 隔开
select * from user where uuid=12700004 and accountType=1 and authType=2\G;
db["user"].find(
{
'$or':[
{"mobile.number":"18874819762"},
{"weixin.unionId":"o1wS90vp2ENW2Vu-QTnHlcrdU5kA"}
]
},
{"weixin.nick":1}
).pretty()select nick from user where number='18874819762' or unionId='o1ws90vp2ENW2Vu-QTnH1crdU5kA'
db["user"].find({'card':{$lt:5}}).pretty() # select * from user where card < 5\G;
db["user"].find({'card':{$gt:0,$lt:5}},{"card":1}).pretty() # select card from user where card > 0 and card <5\G;
db["user"].find({'card':{$lte:5}},{"card":1}).pretty() # select card from user where card <=5;\G;
db["user"].find({'card':{$gte:0,$lte:5}},{"card":1}).pretty() # select card from user where card >=0 and card <=5\G;
db["user"].find({"uuid":{$in:[83405282,25594661]}},{"uuid":1,"card":1}).pretty() # select uuid,card from user where uuid in(83405282,25594661)\G;
db["user"].find({"authType":{$nin:[2,1]}},{"uuid":1,"card":1,"authType":1}).pretty() # select uuid,card,authType from user where authType not in(2,1)\G;
db["user"].find({"liaobe":null},{"uuid":1,"weixin.nick":1,"liaobe":1}).pretty() # select uuid,nick,liaobe from user where liaobei is null\G;
db["user"].find({"weixin.nick":/^随梦/},{"uuid":1,"weixin.nick":1}).pretty() # select uuid,nick from user where nick like '随梦%'\G;
db["user"].find({"weixin.nick":/袋$/},{"uuid":1,"weixin.nick":1}).pretty() # select uuid,nick,from user where nick like '%袋'\G;
db["user"].distinct("weixin.nick",{"weixin.nick":/^随梦/}) # select distinct(nick) from user where nick like "随梦%";
db["user"].find({"card":{$lt:5}}).count() # select count(*) from user where card <5;
db.runCommand( { distinct: "user", key: "weixin.nick", query: { card: {"$lt":5}} } ).values.length; # 先通过find查出数据,然后去重,最后统计
在 MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。
db["user"].find({"card":{$gt:10,$lt:20}},{"uuid":1,"weixin.nick":1,"card":1}).sort({"card":1}) # select uuid,nick,card from user where card>10 and card<20 asc;
db["user"].find({"card":{$gt:10,$lt:20}},{"uuid":1,"weixin.nick":1,"card":1}).sort({"card":-1}) # select uuid,nick,card from user where card>10 and card<20 desc;
如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。
db["user"].find({"card":{$gt:10,$lt:20}},{"uuid":1,"weixin.nick":1,"card":1}).sort({"card":1}).limit(5)
mongodump -u username -p password -h dbhost<:port> -d dbname -o dbdirectory mongodump -h 127.0.0.1:27017 -d test_db -o ./test_db
如果设有帐号密码请加上-u 和-p参数如下:
mongodump -u test -p passwd -h 127.0.0.1:27017 -d test_db -o ./test_db
# root:帐号 xxxx:密码 game_server 数据库名称 sys_config表名称 sys_config.json要导出的表文件
mongoexport -u root -p xxxx -d game_server -c sys_config -o sys_config.json
#没有帐号密码的可以不要 -u -p参数
mongorestore -u username -p password -h <hostname><:port> -d dbname <path>mongorestore -h 127.0.0.1:27017 -d test_db ./test_db
如果设有帐号密码依然请加上-u 和-p参数如下:
mongorestore -u test -p passwd -h 127.0.0.1:27017 -d test_db ./test_db
# root 帐号 xxx 密码 game_server 数据库名称 game_ip_list_config表名称(要恢复的表) game_ip_list_config.json文件名(源数据)
mongoimport -u root -p xxx --db game_server --collection game_ip_list_config --file game_ip_list_config.json
#没有帐号密码的可以不要 -u -p参数
需要添加 --authenticationDatabase admin 参数 ,如导入数据命令:
mongorestore --authenticationDatabase admin -u test -p passwd -h 127.0.0.1:27017 -d test_db ./test_db
mongoDB默认用户认证是关闭的。
修改 /etc/mongod.conf 文件。mongoDB默认情况下任何客户端都可以连接27017端口,且没有认证,默认情况下没有管理员帐户。通过修改这个配置文件可以更改为登陆时进行权限认证。
mongoDB中如果想要给某个数据库创建一个用户,需要首先进入该数据库,然后使用addUser命令。在这里也可以将用户设置为只读(db.addUser("jack","jack",true),第三个参数表示是否时“只读用户”)。
要使用超级管理员,需要先连接admin数据库并登陆管理员帐户,然后连接其他数据库就可以行使管理员权限。
用户信息保存及认证过程
类似MySQL将系统用户信息保存在mysql.user表。MongoDB也将系统用户的username、pwd保存在admin.system.users集合中。其中pwd = md5(username + ":mongo:" + real_password)。这本身并没有什么问题。username和:mongo:相当于对原密码加了一个salt值,即使攻击者获取了数据库中保存的md5 hash,也没法简单的从彩虹表中查出原始密码。