一、基本命令

启动数据库

1
mongod

进入 mongo 命令环境

1
mongo

显示所有数据库

1
show dbs

使用某个数据库,如果当前不存在这个数据库的话会自动新建

1
use 数据库名称

显示数据库内的集合

1
show collections

当前在哪个库中

1
db

CRUD操作 可查看官网文档

新建

数据集合和插入数据,比如当前在 test01 数据库中。
插入数据会自动生成

1
2
3
4
use test01     // 如果当前没有 test01 数据库则会自动新建  
show dbs // 如果 test01 是空白的,使用这个命令 test01 不会显示在结果列表中,必须不是空的才能显示
db.user.insert({"name":"PAN", "age":"18", "job":"web engineer"}) // 在 test01 中插入一个名为 user 的集合
db.user.insert({"name":"TING", "age":"16", "job":"seo manerge"}) // 再插入一条数据

查找

1
2
3
4
db.user.find()    // 查找 user 中的所有数据,这样就可以查看刚刚上面添加的那两条数据了
db.user.find().count() // 长度
db.user.findOne() // 查找集合中符合条件的第一条数据
// db.user.findOnd({age:18}).name

修改

db.集合.updata({条件查询}, {修改})

1
db.user.update({"name":"YU"},{"name":"YONGYU", "age":"19"})  // 需要注意修改的新对象会直接覆盖原来的旧的对象。如果是需要修改指定的属性而不是替换旧对象,参考下面关于updata修改器的教程

删除数据

db.集合.remove({条件})

1
db.user.remove({"name":"001"})

删除集合

db.collection.drop()

1
db.test01.drop()  // 返回 true 表示成功

删除数据库

db.dropDatabase()

1
db.dropDatabase()

二、用JS写mongo语句

1
2
3
4
5
6
7
var userName = "TINGER"; // 定义用户名
var timeStamp = Date.parse(new Date()); // 定义时间戳
var jsonDatabase = {"username": userName, "loginTime": timeStamp} // 要插入的数据
var db = connect('test01'); // 链接 test01 数据库
db.user.insert(jsonDatabase); // user 集合插入数据

print('[log]:: print success!');

三、批量插入

如果是3.2以前版本则需要使用 batchInsert()

1
2
3
4
show dbs
use test02
db.test02.insert([{"_id":1},{"_id":2},{"_id":3}])
db.test02.find() // 查看插入结果

插入性能测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var startTime = (new Date()).getTime();
var db = connect('test02'); // 链接数据库
var tempArr = [];

// 循环插入(不建议)
// for(let i=0; i<1000; i++){
// db.user.insert({num:1})
// }

// 性能优化
for(let i=0; i<1000; i++){
tempArr.push({num:1})
}
db.user.insert(tempArr);

var runTime = (new Date()).getTime() - startTime;

print('[log]:: runtime is '+runTime+'ms');

四、update 修改器

$set 修改

1
2
db.company.update({"name":"TING"},{"$set":{"age":20}}) // 修改 age
db.company.update({"name":"TING"},{"$set":{"skill.s1":"Excel"}}) // 修改嵌套的s1。 skill.s1

$unset 删除

1
2
db.company.update({"name":"TING"},{"$unset":{"age":''}})  // 删除age年龄。age 的值随便写,$unset 时只关心 key
db.company.update({"name":"TING"},{"$set":{"age":20}}) // 重新添加 age。$set 当修改的属性为空时会自己添加

$inc 对数字进行计算

1
db.company.update({"name":"TING"},{"$inc":{"age":-2}})  // age 由原来的值减2

multi选项,有 true 和 false 两个值。默认 false,为 true 时即所有项都添加

1
db.company.update({},{"$set":{"aihao":[]}}, {multi:true})

upsert $set upsert 为 true 添加新项

1
db.company.update({"name":"CUI"},{"$set":{"aihao":[]}}, {upsert:true})  // 如果 CUI 原来不存在,必须 upsert 为 true 才能添加到集合中

五、update数组修改器

$push 追加

1
db.company.update({"name":"TING"},{$push:{"aihao":"shoping"}})  // 在 aihao 项数组中添加 shoping

$ne 查找是否存在。没有则修改,有则不修改。

1
db.company.update({"name":"PAN", "aihao":{$ne:"palygame"}}, {$push:{"aihao":"Game"}}) // ...

$addToSet 查找是否存在,不存在就 push,$ne 的升级版,工作用使用更多

1
db.company.update({"name":"TING"}, {$addToSet:{"aihao":"跳舞"}})

$each 批量追加

1
2
var arr = ['唱歌', '跳舞', '读书'];
db.company.update({"name":"TING"}, {$addToSet:{"aihao":{$each:arr}}})

$pop 删除。1 删除末位,-1删除首位

1
db.company.update({"name":"TING"}, {$pop:{"aihao":1}})

数组定位修改

1
db.company.update({"name":"TING"}, {$set:{"aihao.1":"画画"}})

六、修改的状态返回与安全

runCommand 是数据库运行命令的执行器,执行命令首选就要使用它,因为它在Shell和驱动程序间提供了一致的接口。(几乎操作数据库的所有操作,都可以使用runCommand来执行)

1
2
3
4
db.runCommand():
// 例如
db.runCommand({getLastError:1}}): //getLastError:1 :表示返回功能错误,这里的参数很多,如果有兴趣请自行查找学习,这里不作过多介绍
db.runCommand({ping:1}}): // 查看数据库链接是否成功

findAndModify
findAndModify 属性值

  1. query: 要查询的条件/文档
  2. sort: 进行排序
  3. remove:[boolean]是否删除查找到的文档,值填写true,可以删除。
  4. new:[boolean]返回更新前的文档还是更新后的文档。
  5. fields:需要返回的字段
  6. upsert:没有这个值是否增加。
1
2
3
4
5
6
7
8
var myModify = {
findAndModify: "user",
query: {name: "PAN"},
update: {$set:{age:20}},
new: true
}
var resultMsg = db.runCommand(myModify)
printjson(resultMsg) // 表示以json对象的格式输出到控制台

返回状态结果

1
2
3
4
5
6
7
8
9
10
11
12
{
"lastErrorObject" : {
"updatedExisting" : true, // 成功
"n" : 1
},
"value" : { // 返回修改后的结果
"_id" : ObjectId("5c6d1bac1c8ca3a357fdf9a7"),
"name" : "PAN",
"age" : 20
},
"ok" : 1
}

七、查询:find的不等修饰符

简单查找

1
db.company.find({"skill.skillOne":"HTML+CSS"})

筛选字段
第二个参数控制显示哪些字段。示例:显示 name 和 skill.skillOne 字段,隐藏 _id 字段

1
db.company.find({"skill.skillOne":"HTML+CSS"},{name:true,"skill.skillOne":true,_id:false})

不等修饰符
小于($lt): 英文全称less-than
小于等于($lte):英文全称less-than-equal
大于($gt): 英文全称greater-than
大于等于($gte): 英文全称greater-than-equal
不等于($ne):英文全称not-equal 我们现在要查找一下,公司内年龄小于30大于25岁的人员。看下面的代码。
示例:查询年龄大于等于 25,小于等于 30 的人

1
db.company.find({"age":{$gte:25,$lte:30}},{name:true,"skill.skillOne":true,_id:false,age:true})

查找日期
示例:查找日期大于2018-01-01的

1
2
var regTime = new Date("01/01/2018");
db.company.find({"regeditTime":{$gt:regTime}},{name:true,"skill.skillOne":true,_id:false,age:true,regeditTime:true})

八、查询:find的多条件查询

$in修饰符,一键多值,注意 $in 的值是一个数组
示例:查找年龄等于 25 和 33 岁的

1
db.company.find({"age":{$in:[25,33]}},{name:1,"skill.skillOne":1,_id:0,age:1})

$in修饰符,和 $in 相反,就是不包含查询条件的

1
db.company.find({"age":{$nin:[25,33]}},{name:1,"skill.skillOne":1,_id:0,age:1})

$or,或者,类似JS中的或运算 ||
示例:查找年龄大于行于30或者技能会PHP的

1
2
3
4
db.company.find({$or:[
{age:{$gte:30}},
{"skill.skillThree":"PHP"}
]},{name:1,"skill.skillThree":1,_id:0,age:1})

$and,并且,类似JS中的或运算 &&
示例:查找年龄大于行于30并且技能会PHP的

1
2
3
4
db.company.find({$and:[
{age:{$gte:30}},
{"skill.skillThree":"PHP"}
]},{name:1,"skill.skillThree":1,_id:0,age:1})

$not修饰符
查找除年龄大于20岁,小于30岁的人员信息。需要注意的是$not修饰符不能应用在条件语句中,只能在外边进行查询使用。

1
2
3
4
5
6
7
8
9
10
db.workmate.find({
age:{
$not:{
$lte:30,
$gte:20
}
}
},
{name:1,"skill.skillOne":1,age:1,_id:0}
)

九、查询:find数组查询

基本数组查询
示例:查询兴趣(interest)中有画画的人员

1
2
3
db.workmate.find({interest:'画画'},{name:1,interest:1,_id:0})
// 如果画画加了数组的中括则表示要完全匹配条件,例如以下示例则表示要完全匹配有画画和看电影的
db.workmate.find({interest:['画画','看电影']},{name:1,interest:1,_id:0})

$all 数组多项查询
示例:查询兴趣中同时存在画画和看电影两项的

1
db.workmate.find({interest:{$all:["画画","看电影"]}},{name:1,interest:1,_id:0})

$in 数组的或查询
类似JS的或运算,示例:查询兴趣中有画画或者看电影一项的结果

1
db.workmate.find({interest:{$in:["画画","看电影"]}},{name:1,interest:1,_id:0})

$size 数组个数查询
示例:显示兴趣项长度为3的项

1
db.workmate.find({interest:{$size:3}},{name:1,interest:1,_id:0})

$slice 控制显示长度
示例:只显示兴趣数组前两项,也也接受负数,如果-1表示最后一项

1
db.workmate.find({interest:{$size:3}},{name:1,interest:{$slice:2},_id:0})

十、查询:find参数

find查询包含以下几个参数query, fields, limit, skip, batchSize, options,前面的示例用的一直都是query和fields
query:这个就是查询条件,MongoDB默认的第一个参数。
fields:(返回内容)查询出来后显示的结果样式,可以用true和false控制是否显示。
limit:返回的数量,后边跟数字,控制每次查询返回的结果数量。
skip:跳过多少个显示,和limit结合可以实现分页。
sort:排序方式,从小到大排序使用1,从大到小排序使用-1

示例:limit显示4条,跳过0条

1
2
3
4
5
db.workmate.find({},{name:1,age:1,_id:0}).limit(4).skip(0)
如果要做分页可以如下编写
db.workmate.find({},{name:1,age:1,_id:0}).limit(4).skip(0) // 第一页,每页显示4条,跳过0条数据
db.workmate.find({},{name:1,age:1,_id:0}).limit(4).skip(4) // 第二页,每页显示4条,跳过4条数据
db.workmate.find({},{name:1,age:1,_id:0}).limit(4).skip(8) // 第三页,每页显示4条,跳过8条数据

示例:对年龄排序,1表示从小到大排序

1
db.workmate.find({},{name:1,age:1,_id:0}).limit(4).skip(0).sort({age:1})

十一、索引入门

普通查询性能测试

1
2
3
4
5
6
7
8
var startTime = (new Date).getTime();

var db = connect('test02');
var rs = db.randomInfo.find({username:'dnaugkj'});
rs.forEach(rs=>{printjson(rs)})

var runTime = (new Date).getTime() - startTime;
print('[SUCCESS]This run time is:'+runTime+'ms');

示例结果,大概需要600-800毫秒左右,具体结果和机器有一定关系。

查看索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
db.randomInfo.getIndexes()  // randomInfo 为 collections 名称
// 查询结果
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test02.randomInfo"
},
{
"v" : 2,
"key" : {
"username" : 1
},
"name" : "username_1",
"ns" : "test02.randomInfo"
}
]

建立索引
MongoDB 最多只能建立 64 个索引,索引会消耗硬盘和内存资源。

1
2
db.randomInfo.ensureIndex({username:1})
// 如果运行正确,建立之后使用 getIndexes 即可查看

建立索引之后再运行一下上面普通查询的代码会发现查询速度会极大提升,约5-10毫秒左右

删除索引

1
db.randomInfo.dropIndex('username_1');  // 注意值不是 key 值,而是 name 值

查看运行时间

1
db.randomInfo.find({username:'dnaugkj'}).explain("executionStats");

十二、复合索引

数据不超万条时,不需要使用索引。性能的提升并不明显,而大大增加了内存和硬盘的消耗。
查询数据超过表数据量30%时,不要使用索引字段查询。实际证明会比不使用索引更慢,因为它大量检索了索引表和我们原表。
数字索引,要比字符串索引快的多,在百万级甚至千万级数据量面前,使用数字索引是个明确的选择。
把你经常查询的数据做成一个内嵌数据(对象型的数据),然后集体进行索引。

复合索引就是两个以上的索引

1
2
3
4
5
6
7
8
var startTime = (new Date).getTime();

var db = connect('test02');
var rs = db.randomInfo.find({username:'dnaugkj', randNum0:940739});
rs.forEach(rs=>{printjson(rs)})

var runTime = (new Date).getTime() - startTime;
print('[SUCCESS]This run time is:'+runTime+'ms');

指定索引查询(hint)
使用 hint() 方法指定索引优先查询

1
2
3
...e
var rs = db.randomInfo.find({username:'dnaugkj', randNum0:940739}).hint({randNum0:1}); // randNum0 优先查询
...

十四、全文索引

建立全文索引

1
db.info.ensureIndex({"contextInfo":"text"})

全文索引查找
查找时需要配合两个关键修改符
$text:表示要在全文索引中查东西。
$search:后边跟查找的内容。

1
db.info.find({$text:{$search:"programmer"}})

多词查询
示例:查询包含 drink 或者 life 的记录

1
db.info.find({$text:{$search:"drink life"}})

可以用 - 来排队不需要的记录。示例:排队带有 drink 的记录项

1
db.info.find({$text:{$search:"-drink life"}})

转义符

1
2
想搜索的是两个词(love PlayGame和drink)
db.info.find({$text:{$search:"\"love PlayGame\" drink"}})

十五、管理:用户的创建、删除与修改

创建用户首先要进入 admin 库,show collections 只有 version 一个集合

1
2
3
show dbs
use admin
show collections

创建用户
使用 createUser 创建数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
db.createUser({
user:"pan", // 用户名
pwd:"123456", // 密码
customData:{ // 个性信息
name:"潘",
age:18
},
roles:[ // 配置权限
{
role:'readWrite', // test02 有读写权限
db:'test02',
},
'read' // 其他所有库只有吟诗权限
]
})

内置角色
数据库用户角色:read、readWrite;
数据库管理角色:dbAdmin、dbOwner、userAdmin;
集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManage;
备份恢复角色:backup、restore;
所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
超级用户角色:root
内部角色:__system

查找用户信息

1
db.system.users.find()

删除用户

1
db.system.users.remove({user:"pan"})

十六、备份和还原

备份

1
2
3
4
5
6
7
8
9
mongodump
--host 127.0.0.1
--port 27017
--out D:/databack/backup
--collection myCollections
--db test
--username username
--password password
mongodump --host 127.0.0.1 --port 27017 --out /Users/panyongyu/Documents/study/mongodb/backup

还原

1
2
3
4
5
6
7
mongorestore
--host 127.0.0.1
--port 27017
--username username
--password password
<path to the backup>
mongorestore --host 127.0.0.1 --port 27017 --out /Users/panyongyu/Documents/study/mongodb/backup

评论