<p id="main-toc"><strong>目录</strong></p>
MongoDB一律采用小驼峰命名法
一、MongoDB的安装
1.1 MongoDB的下载安装
1.2 环境变量的配置
右键此电脑,点击属性,点击高级系统设置,点击环境变量
进入刚才安装的MongoDB的bin目录,复制路径,添加在环境变量中
1.3 启动Mongo服务
命令行中执行 mongod
手动创建完data/db目录之后,再次执行mongod
说明Mongo服务已经启动成功
1.4 初体验
再次打开一个终端,执行mongo命令连接数据库
二、MongoDB基本命令
2.1 基本命令1
2.2 基本命令2
2.2.1 增加数据
show dbs 查看所有数据库
use user 使用该数据库(没有则自动创建)
db 查看当前数据库
show collections 查看当前数据库下的集合
db.user.insert({"name":"Hamy"}) 给user集合中插入一条数据
db.user.find() 查看当前集合下的所有数据
db.user.findOne() 查看当前集合下的第一条数据
MongoDB会自动添加一条_id索引
再次插入两条数据,然后查询
2.2.2 修改数据
db.user.updata({"name":"Hamy"},{"name":"Hamy","age",18}) 修改name为Hamy的用户age为18,没有则创建
2.2.3 删除
db.user.remove({"name":"Hamy"}) 删除数据
db.user.drop() 删除集合
db.user.dropDatabase() 删除数据库
三、用JavaScript来写命令
新建一个js文件goTask.js
var userName="xueshuai"; //定义一个用户名 var password="xueshuai"; //定义一个密码 var jsonDatabase={"loginName":userName,"loginPassword":password}; //生成json字符串 var db=connect('user'); //相当于在终端中执行use user,进入数据库 db.login.insert(jsonDatabase) //给该数据库中login集合插入一条数据
print('[demo]:log print success') //打印插入成功
打开终端进入该js的目录下执行mongo goTask.js
最下面会有日志打印成功
接下来查看当前数据库中是否存在该数据
首先打开终端执行mongo命令,连接数据库
其次"查看所有数据库","使用数据库","查看所有集合","查询该集合下的所有数据",可以看到数据存入成功
四、MongoDB插入的批量操作
db.test.insert([{"_id":1},{"_id":2},{"_id":3}]) //执行这条命令会在test集合中插入三条数据
db.test.find() //执行这条命令会查找该test集合中的所有数据
在实际工作中建议采用批量插入的方法插入数据,循环插入耗费性能(循环插入可能需要584ms,批量插入可能只需要84ms)
var startTime = (new Date()).getTime();//获取开始时间 var db=connect('log');//连接数据库 //循环插入 /* for(let i=0;i<1000;i++){ db.test.insert({num:i});//插入数据 } */
//批量插入
var tempArray = [];
for(let i=0;i<1000;i++){
tempArray.push({num:i});
}
db.test.insert(tempArray)//插入数组
var runTime = (new Date()).getTime() - startTime;
print("[demo]This run is " + runTime + 'ms')
五、MongoDB Updata常见错误
5.1 在数据库中准备数据
var workmate1={
name:'JSPang',
age:33,
sex:1,
job:'PHP后端',
skill:{
skillOne:'HTML+CSS',
skillTwo:'JavaScript',
skillThree:'PHP'
},
regeditTime:new Date()
}
...
var db=connect('company');//连接数据库
var workmateArray=[workmate1,workmate2,workmate3];//将所有的数据放在一个数组中
db.workmate.insert(workmateArray);//批量插入数据
print('[success]:The data was inserted successfully')//打印
打开VSCode,首先执行mongo命令,然后加载该js文件,最后去集合中查找有没有数据
5.2 修改
情景:修改LiLy的性别
/****错误示范****/
var db=connect('company')//连接数据库
db.workmate.update({name:'LiLy'},{sex:1})//修改name为LiLy的性别为1
print('[update]:The data was updated successfully')
//看似并没有任何问题,但是当执行完这个文件之后,LiLy的资料只剩一个sex为1,其余资料全被删除
/****正确示范****/
//在一个对象中修改值
var workmate3={
name:'LiLy',
age:18,
sex:1,
job:'UI',
skill:{
skillOne:'PhotoShop',
skillTwo:'UI',
skillThree:'PPT'
},
regeditTime:new Date()
}
var db=connect('company')
//先查找要修改的数据,用修改后的wormate3覆盖原先的数据
db.workmate.update({name:'LiLy'},workmate3)
print('[update]:The data was updated successfully')
六、初始Update修改器
6.1 $set修改器
//修改workmate集合中name为LiLy的性别为0,年龄为20,且不会影响到其他字段 db.workmate.update({name:'LiLy'},{"$set":{sex:0,age:20}})
//内嵌数据的修改,skill下有skillOne、skillTwo、skillThree
db.workmate.update({name:'LiLy'},{$set:{"skill.skillThree":"word"}})
6.2 $unset修改器
//找到name为LiLy的用户删除年龄,age后面的值可以为空,也可以为-1,可以为任意值,只关注key值
db.workmate.update({name:'LiLy'},{$unset:{age:''}})
//找到name为LiLy的用户,添加年龄,使用$set修饰符
db.workmate.update({name:'LiLy'},{"$set":{age:20}})
6.3 $inc修改器
//找到name为LiLy的用户,修改年龄为18,使用$inc修饰符,在原来的年龄基础上-2
db.workmate.update({name:'LiLy'},{"$inc":{age:-2}})
6.4 multi选项用法
//给所有的用户添加一个interest字段
//multi:true(查找到第一条继续往下查找) false(只查找一条,默认)
db.workmate.update({},{"$set":{interest:[]}},{multi:true})
6.5 upsert选项用法
//修改name为xiaoWang的用户年龄为20
//upsert:true(如果没找到就添加) false(如果没找到就不添加,默认)
db.workmate.update({name:"xiaoWang"},{"$set":{age:20}},{upsert:true})
七、Update数组修改器
7.1 $push修改器
//给name为xiaoWang的用户添加interest为draw
db.workmate.update({name:"xiaoWang"},{$push:{interest:'draw'}})
//给name为LiLy的用户添加skill的skillFour为draw,依然是以数组的形式
db.workmate.update({name:"LiLy"},{$push:{"skill.skillFour":'draw'}})
7.2 $ne修改器
//查找name为xiaoWang的用户的interest里面有没有playGame的爱好,如果没有则添加,有则不添加
db.workmate.update({name:"xiaoWang",interest:{$ne:'playGame'}},{$push:{interest:'Game'}})
7.3 $addToSet修改器
//$ne的升级版
//查找name为xiaoWang的用户有没有readBook的interest,没有则添加,有则不添加
db.workmate.update({name:"xiaoWang"},{$addToSet:{interest:'readBook'}})
7.4 $each修改器
//查找name为xiaoWang的用户批量添加interest,首先定义变量保存要添加的内容,使用$each批量添加
var newInterests = ['Sing','Dance','Code'];
db.workmate.update({name:"xiaoWang"},{$addToSet:{interest:{$each:newInterests}}})
7.5 $pop修改器
//$pop 1(从末端开始删除) -1(从开始位置删除)
//查找name为xiaoWang的用户,删除interest中最后一项
db.workmate.update({name:"xiaoWang"},{$pop:{interest:1}})
7.6 数组定位修改
//查找name为xiaoWang的用户,修改interest的下标为2的改为Code
db.workmate.update({name:"xiaoWang"},{$set:{"interest.2":"Code"}})
七、findAndModify
7.1 runCommand()
//给所有sex为1的用户添加一个字段money为1000 //第一个false表示如果没有找到sex为1的用户不增加,true表示查找完之后还会继续查找(找到所有sex为1的用户) db.workmate.update({sex:1},{$set:{money:1000}},false,true)
var resultMessage = db.runCommand({getLastError:1})//查看返回值
/*
//执行安全操作
if(resultMessage.updatedExisting){}else{
}
*/
printjson(resultMessage)
//可以通过如下命令查看当前数据库是否连接成功
db.runCommand({ping:1})
//成功则会返回
{ "ok" : 1 }
7.2 findAndModify()
//定义一个对象,传入参数
var myModify = {
findAndModify:"workmate",//修改的集合
query:{ name:"JSPang" },//查找条件
update:{$set:{age:18}},//修改为
new:true//true为修改后的值,false为修改前的值
}
//定义一个变量接收返回值
var resultMessage = db.runCommand(myModify);
//将返回值打印出来
printjson(resultMessage);
八、MongoDB查询_不等修饰符
//查询skill的skillOne为HTML+CSS的用户
db.workmate.find(
{"skill.skillOne":"HTML+CSS"},//查询条件
{name:true,"skill.skillOne":true,"_id":false} //返回规则(true为需要返回,false为不需要返回)
)
//查询年龄大于等于25小于等于30的用户
db.workmate.find(
{age:{$lte:30,$gte:25}},
{name:true,"skill.skillOne":true,age:true,"_id":false}
)
//查找注册日期大于01/01/2018日期的用户
var startDate = new Date('01/01/2018');
db.workmate.find(
{regeditTime:{$gt:startDate}},
{name:true,"skill.skillOne":true,age:true,"_id":false}
)
九、MongoDB查询_多条件查询
//查询age为25或33的用户(多条件查询) //$in 一个key多个value查询 db.workmate.find( {age:{$in:[25,33]}}, {name:true,"skill.skillOne":true,age:true,_id:false} )
//查询age除了25和33的用户
//$nin 不包含查询
db.workmate.find(
{age:{$nin:[25,33]}},
{name:true,"skill.skillOne":true,age:true,_id:false}
)
//查询age大于等于30或者skill.skillThree等于PHP的用户
//$or 多key多value查询
db.workmate.find(
{$or:[
{age:{$gte:30}},
{"skill.skillThree":"PHP"}
]},
{name:true,"skill.skillThree":true,age:true,_id:false}
)
//查询age大于等于20小于等于30之外的用户
//$not
db.workmate.find(
{age:{$not:{$lte:30,$gte:20}}},
{name:true,"skill.skillThree":true,age:true,_id:false}
)
十、MongoDB查询_数组查询
//查询interest为'画画','聚会','看电影'的用户 db.workmate.find( {interest:['画画','聚会','看电影']}, {name:true,interest:true,age:true,_id:false} )
//查询interest中有'画画'的用户
db.workmate.find(
{interest:'画画'},//'画画'不能加中括号,加中括号属于完全匹配
{name:true,interest:true,age:true,_id:false}
)
10.1 $all修饰符
//查询interest中既有'看电影',又有'看书'的用户
db.workmate.find(
{interest:{$all:['看电影','看书']}},
{name:true,interest:true,age:true,_id:false}
)
10.2 $in修饰符
//查询interest中有'看电影'或'看书'的用户
//$in
db.workmate.find(
{interest:{$in:['看电影','看书']}},
{name:true,interest:true,age:true,_id:false}
)
10.3 $size修饰符
//查询interest中有5项的用户
//$size
db.workmate.find(
{interest:{$size:5}},
{name:true,interest:true,age:true,_id:false}
)
10.4 $slice修饰符
//查询interest中有3项的用户并且返回第一项 //$slice db.workmate.find( {interest:{$size:3}}, {name:true,interest:{$slice:1},age:true,_id:false} )
//显示前两项
db.workmate.find(
{interest:{$size:3}},
{name:true,interest:{$slice:2},age:true,_id:false}
)//显示最后一项
db.workmate.find(
{interest:{$size:3}},
{name:true,interest:{$slice:-1},age:true,_id:false}
)
//显示区间项
//显示从下标为0项到下标为3项
db.workmate.find(
{interest:{$size:5}},
{name:true,interest:{$slice:[0,3]},age:true,_id:false}
)
十一、MongoDB查询_参数使用方法
//查询所有,分页显示
//分页 每页显示两个 年龄从小到大
//sort 1(从小到大) -1(从大到小)
db.workmate.find(
{},
{name:true,age:true,_id:false}
).limit(2).skip(0).sort({age:1})
//查询age大于30的用户
//$where
db.workmate.find(
{$where:"this.age>30"},//this指代的是workmate集合
{name:true,age:true,_id:false}
)
能普通查询尽量不使用$where查询
- 不安全
- 加重了数据库的负担
十二、MongoDB查询_如何在js文本中使用
//在js中写下如下代码,终端中执行mongo,然后load('当前文件路径.js')就可以执行 //hasNext() var db = connect('company'); var result = db.workmate.find();//将查到的所有数据赋值给一个变量,最后打印这个变量
//方法一:while
// while(result.hasNext()){
// printjson(result.next())
// }
//方法二:forEach()
result.forEach(function(result){
printjson(result);
})
十三、MongoDB索引_构造百万级数据表
首先需要安装node.js环境
- 使用node.js是为了测试随机数和随即用户名是否正确
- 在执行mongo命令,执行load('当前文件路径.js'),运行这段js存储在MongoDB的时候,不能有console.log,mongoShell不支持
//生成随机数 function GetRandomNum(min,max){ let range = max-min;//随机区间 10 let rand = Math.random();//随机数 0-1 return (min+Math.round(rand*range));//10+([0-1]*10) } //console.log(GetRandomNum(10,20))
//生成随机用户名
function GetRadomUserName(min,max){
let tempStringArray = "123456789qwertyuiopasdfghjklzxcvbnm".split("");//是个数组
let outputtext = "";//输出的用户名
for(let i=1;i<GetRandomNum(min,max);i++){//用户名的长度是一个随机数
outputtext= outputtext + tempStringArray[GetRandomNum(0,tempStringArray.length-1)]//用户名应该是由tempStringArray数组中的每一项拼成
}
return outputtext;
}
//console.log(GetRadomUserName(7,16));//批量插入两百万条数据
var startTime = (new Date()).getTime();//获取开始时间
var tempInfo=[];
for(let i=0;i<2000000;i++){
tempInfo.push({
username:GetRadomUserName(7,16),
regediteTime:new Date(),
randNum0:GetRandomNum(100000,999999),
randNum1:GetRandomNum(100000,999999),
randNum2:GetRandomNum(100000,999999),
randNum3:GetRandomNum(100000,999999),
randNum4:GetRandomNum(100000,999999),
randNum5:GetRandomNum(100000,999999),
randNum6:GetRandomNum(100000,999999),
randNum7:GetRandomNum(100000,999999),
randNum8:GetRandomNum(100000,999999),
randNum9:GetRandomNum(100000,999999),
})
}var db = connect('company');//连接数据库
db.randomInfo.drop();//先删除原有的randomInfo库
db.randomInfo.insert(tempInfo);//然后添加现在的库
var endTime = (new Date()).getTime() - startTime;//计算耗时
print("[总共耗时]:----------"+endTime+"ms")
由图可见,还是很快的
十四、MongoDB索引_建立索引
var startTime = (new Date()).getTime();
var db = connect('company');
var rs = db.randomInfo.find({username:'9wobojo'});//从数据库中任意取到的一个usernamers.forEach(rs => printjson(rs) );//打印当前这个数据
var runTime = new Date().getTime() - startTime;
print('[demo]:this run time is '+runTime+'ms');
//普通查询可能需要1000-2000ms的时间//查看索引
db.randomInfo.getIndexes()
//数组中有几个对象就有几个索引,mongodb默认有一个id索引,最多支持64个索引
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "id",
"ns" : "company.randomInfo"
}
]//建立索引
db.randomInfo.ensureIndex({username:1})
//建立索引之后再次查看索引,可以看到有了两个索引
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "id",
"ns" : "company.randomInfo"
},
{
"v" : 2,
"key" : {
"username" : 1
},
"name" : "username_1",
"ns" : "company.randomInfo"
}
]
//建立索引之后再次查询可能只需要几毫秒
十五、MongoDB索引_复合索引
15.1 复合索引
所谓的复合索引,就是多条索引查询
首先再建一条索引
db.randomInfo.ensureIndex({randNum0:1})
username索引是字符串索引
randNum索引是数字索引
MongoDB根据索引查询的顺序是通过如下查询的
> db.randomInfo.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "id",
"ns" : "company.randomInfo"
},
{
"v" : 2,
"key" : {
"username" : 1
},
"name" : "username_1",
"ns" : "company.randomInfo"
},
{
"v" : 2,
"key" : {
"randNum0" : 1
},
"name" : "randNum0_1",
"ns" : "company.randomInfo"
}
]
如果想优先使用randNum索引查询需要使用hint方法
db.randomInfo.find({username:'e89aamcvz',randNum0:942055}).hint({randNum0:true})
15.2 删除索引
db.randomInfo.dropIndex('randNum0_1')
括号里的内容填写的是该索引的name值
通过如下命令查看索引
db.randomInfo.getIndexes()
十六、MongoDB索引_全文索引
16.1 插入数据
首先测试,先在info集合中插入两条数据
db.info.insert({contextInfo:"I am a programmer, I love life, love family. Every day after work, I write a diary."})
db.info.insert({contextInfo:"I am a programmer, I love PlayGame, love drink. Every day after work, I playGame and drink."})
16.2 建立全文索引
db.info.ensureIndex({contextInfo:'text'})
//查询全文中有programmer的内容 db.info.find({$text:{$search:'programmer'}})
//查询全文中有programmer 或 family 或 diary 或 drink的内容
db.info.find({text:{search:'programmer family diary drink'}})//查询全文中有programmer 或 family 或 diary的内容,但是不查找drink的内容
db.info.find({text:{search:'programmer family diary -drink'}})
//查询全文中有"love PlayGame"或drink的内容
//如果两个词之间有空格,MongoDB提供了转义符的形式 " "
db.info.find({text:{search:""love PlayGame" drink"}})
十七、MongoDB用户的创建删除和管理
17.1 创建管理员
mongo服务启动之后,首先需要进入admin数据库
use admin
然后创建管理员
//创建管理员 db.createUser({ user:'jspang',//用户名 pwd:'123456',//密码 customData:{//管理员数据 name:'技术胖', email:'web0432@126.com', age:18 }, roles:[//权限 { role:"readWrite",//拥有读写权限 db:"company"//对company数据库拥有权限 }, 'read'//其他用户拥有只读权限 ] })
//查询存在的管理员
db.system.users.find()
//删除管理员
db.system.users.remove({user:'jspang'})
建权
//管理员账号密码 db.auth("jspang","123456")
//建权之后启动mongod使用
mongod --auth//启用mongo服务时使用
//mongo -u 用户名 -p 密码 ip:端口/admin
mongo -u jspang -p 123456 127.0.0.1:27017/admin//进入数据库
use company//查询集合
show collections
...
十八、MongoDB数据库的备份和还原
首先开启服务
然后执行备份命令
mongodump --host 127.0.0.1 //ip地址 --port 27017 //端口 --out D:/backup //备份存在的目录 --collection randomInfo //需要备份的集合 --db company //需要备份的数据库 --username username //用户名 --password password //密码
例:
//备份所有数据到D:/backup目录
mongodump --host 127.0.0.1 --port 27017 --out D:/backup/
mongodump -h 127.0.0.1:27017 -d <数据库名> -o <备份路径[需先创建]>
恢复命令
mongorestore --host 127.0.0.1 //ip --port 27017 //端口 --username username //用户名 --password password //密码 <path to the backup> //备份的路径
例:
//mongod服务需要先启用 c盘根目录下要先有C:\data\db 目录
mongorestore --host 127.0.0.1 --port 27017 D:/backup/
当使用 mongo 的一些命令提示 “不是内部或外部命令,也不是可运行的程序或批处理文件” 的时候,你可能下载的mongodb不完整,需要 点击这里 下载zip
解压之后将 bin 目录下的内容复制到 mongodb 的 bin 目录下即可
十九、MongoDB数据库的图形化界面
启动图形化界面之前,首先需要启动mongod服务
可以看到MongoDB下的所有数据库,点击数据库可显示集合,点击集合可查看集合中的数据
查询数据
修改数据
创建集合
MongoDB基础教程到此结束,皆根据JSPang的个人博客教程记录的个人笔记。
不积跬步,无以至千里