美文网首页
MongoDB教程(入门篇)

MongoDB教程(入门篇)

作者: 简栋梁 | 来源:发表于2019-06-16 22:53 被阅读0次

目录
一、基本命令
二、使用js编写命令,代替在cli中编写
三、修改
四、查询
五、索引
六、管理
七、mongoose

系列教程
MongoDB教程(初识篇)


一、基本命令

命令 功能
show dbs 显示已有数据库
use 库 进入数据库(不存在的库,立即创建)
show collections 显示已有集合
db 显示当前所在的数据库
db.集合.insert() 增(不存在的集合,立即创建,下面同理)
db.集合.remove()
db.集合.update()
db.集合.find()
db.集合.findOne() 查,显示第一条数据
db.集合.drop() 删集合
db.dropDatabase() 删库
db.version() 查看数据库版本

二、使用js编写命令,代替在cli中编写

//goTask1.js
const userName="tony"     //声明一个登录名
const timeStamp=Date.parse(new Date())     //声明登录时的时间戳
const jsonDatabase={"loginUser":userName,"loginTime":timeStamp}     //组成JSON字符串
const db = connect('log')     //链接数据库log
db.login.insert(jsonDatabase)     //插入数据
print('ok')     //没有错误显示成功

//运行脚本,执行命令
mongo goTask1.js


//goTask2.js
//遇到需要插入多条数据的情况,使用数组一次性插入数据,比循环单条数据插入的性能更好
//批量插入时,每次插入的数据量,不能多于48MB
const jsonDatabase1={"loginUser":"tony","loginTime":Date.parse(new Date())}
const jsonDatabase2={"loginUser":"jenny","loginTime":Date.parse(new Date())}
const jsonDatabase3={"loginUser":"gogo","loginTime":Date.parse(new Date())}
const db = connect('log')
db.login.insert([jsonDatabase1, jsonDatabase2, jsonDatabase3])
print('ok')

//运行脚本,执行命令
mongo goTask2.js

三、修改

1、普通修改(不使用update修改器)
//普通修改,新记录填什么,数据就替换成什么
const workmate={
    name:'tony',
    age:33,
    sex:1,
    job:'前端',
    skill:{
        skillOne:'HTML+CSS',
        skillTwo:'JavaScript',
        skillThree:'PHP'
    },
    regeditTime:new Date(),
    interest:[]
}
//原目的是修改tony的年龄,但是以下的写法,会将数据只保留age:18这一字段
db.workmate.update({name:'tony'},{age:18})

//正确做法
workmate.age=18
db.workmate.update({name:'tony'},workmate)
2、初识update修改器

(1)$set

//$set:修改部分字段
db.workmate.update({"name":"tony"},{"$set":{sex:2,age:21}})

//修改嵌套内容
db.workmate.update({"name":"tony"},{"$set":{"skill.skillThree":'word'}})

(2)$unset

//$unset:删除部分字段
db.workmate.update({"name":"tony"},{$unset:{"age":''}})

(3)$inc

//$inc:对数字进行计算,只能修改数字类型
db.workmate.update({"name":"tony"},{$inc:{"age":-2}})    //年龄减小2

(4)multi选项

//multi:true表示对所有数据,设置该字段
db.workmate.update({},{$set:{interset:[]}},{multi:true})

(5)upsert选项

//upsert:true表示若匹配的数据不存在,自动插入改数据(name),再进行数据更新(age)
db.workmate.update({name:'jenny'},{$set:{age:20}},{upsert:true})
3、update数组修改器

(1)$push

//$push:追加数组索引项
db.workmate.update({name:'tony'},{$push:{interest:'draw'}})

(2)$ne

//$ne:查找字段是否存在
//如果tony的interest里没有palyGame,我们就加入Game这个爱好
db.workmate.update({name:'tony',"interest":{$ne:'playGame'}},{$push:{interest:'playGame'}})

(3)$addToSet

//$addToSet:便捷版的$ne
//如果tony的interest里没有readBook,我们就加入readBook这个爱好
db.workmate.update({name:"tony"},{$addToSet:{interest:"readBook"}})

(4)$each

//$each:批量追加
const newInterset=["Sing","Dance","Code"]
db.workmate.update({name:"tony"},{$addToSet:{interest:{$each:newInterset}}})

(5)$pop

//$pop:删除一个数组索引项
//-1:从头部开始
//1:从尾部开始
db.workmate.update({name:'tony'},{$pop:{interest:1}})

(6)数组定位修改

//.num:定位数组的第num+1项
//修改tony的第二个interest项为YY
db.workmate.update({name:'tony'},{$set:{"interest.2":"YY"}})
4、状态返回与安全

(1)db.runCommand(应答式写入)

//false:第一句末尾的false是upsert的简写,代表没有此条数据时不增加
//true:true是multi的简写,代表修改所有,这两个我们在前边课程已经学过
//getLastError:1 :表示返回功能错误,这里的参数还有很多
//printjson:表示以json对象的格式输出到控制台
db.workmate.update({sex:1},{$set:{money:1000}},false,true)
const resultMessage=db.runCommand({getLastError:1})    //使用应答式写入
printjson(resultMessage);

(2)findAndModify

const myModify={
    findAndModify:"workmate",
    query:{name:'tony'},
    upsert:{$set:{age:18}},
    new:true    //更新完成,需要查看结果,如果为false不进行查看结果
}
const ResultMessage=db.runCommand(myModify);

printjson(ResultMessage)

(3)findAndModify选项

选项 功能
query 需要查询的条件/文档
sort 进行排序
remove [boolean]是否删除查找到的文档,值填写true,可以删除。
new [boolean]返回更新前的文档还是更新后的文档。
fields 需要返回的字段
upsert 没有这个值是否增加。

四、查询

1、find的不等修饰符

(1)普通查找

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

(2)筛选字段

//查询结果只显示该数据的name、skill.skillOne字段
db.workmate.find(
    {"skill.skillOne":"HTML+CSS"},
    {name:true,"skill.skillOne":true}
)

(3)不等修饰符

名称 含义
$lt 小于(less-than)
$lte 小于等于(less-than-equal)
$gt 大于(greater-than)
$gte 大于等于(greater-than-equal)
$ne 不等于(not-equal)

(4)范围查找

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

(5)日期查找

const startDate= new Date('01/01/2018');
db.workmate.find(
    {regeditTime:{$gt:startDate}},    //值为Date对象
    {name:true,age:true,"skill.skillOne":true,_id:false}
)
2、find的多条件查询

(1)$in

//同一字段中,挑选
db.workmate.find(
    {age:{$in:[25,33]}},
    {name:1,"skill.skillOne":1,age:1,_id:0}
)

(2)$or

//$or:或者
db.workmate.find(
    {$or:[
        {age:{$gte:30}},
        {"skill.skillThree":'PHP'}
    ]},
    {name:1,"skill.skillThree":1,age:1,_id:0}
)

(3)$and

//$and:并且
db.workmate.find(
    {$and:[
        {age:{$gte:30}},
        {"skill.skillThree":'PHP'}
    ]},
    {name:1,"skill.skillThree":1,age:1,_id:0}
)

(4)$not

//$not:取反
db.workmate.find({
    age:{
        $not:{
            $lte:30,
            $gte:20
        }
    }
},
{name:1,"skill.skillOne":1,age:1,_id:0}
)

(5)$where

db.workmate.find(
    {$where:"this.age>30"},
    {name:true,age:true,_id:false}
)

PS:这里的this指向的是workmate(查询集合)本身。这样我们就可以在程序中随意调用。虽然强大和灵活,但是这种查询对于数据库的压力和安全性都会变重,所以在工作中尽量减少$where修饰符的使用。

3、find的数组查询

(1)普通数组查询

//查询interest中包含画画、聚会、看电影的数据
db.workmate.find({interest:['画画','聚会','看电影']},
    {name:1,interest:1,age:1,_id:0} 
)

(2)$all

//条件:数组中,包含以下项
db.workmate.find(
    {interest:{$all:["看电影","看书"]}},
    {name:1,interest:1,age:1,_id:0} 
)

(3)$in

//条件:数组中,包含其中一项
db.workmate.find(
    {interest:{$in:["看电影","看书"]}},
    {name:1,interest:1,age:1,_id:0} 
)

(4)$size

//条件:数组长度为指定值
db.workmate.find(
    {interest:{$size:5}},
    {name:1,interest:1,age:1,_id:0} 
)

(5)$slice

//显示数组的头两项
db.workmate.find(
    {},
    {name:1,interest:{$slice:2},age:1,_id:0} 
)

//显示数组的尾一项
db.workmate.find(
    {},
    {name:1,interest:{$slice:-1},age:1,_id:0} 
)
4、find的多参数实现分页

(1)find参数

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

(2)分页实现

db.workmate.find({},{name:true,age:true,_id:false}).limit(0).skip(2).sort({age:1});
5、find如何在js中使用

(1)使用前提
find返回的结果集,是一个数组,必须进行遍历,逐条输出。

(2)hasNext()控制游标

const db = connect("company")  //进行链接对应的集合collections
const result = db.workmate.find() //声明变量result,并把查询结果赋值给result
//利用游标的hasNext()进行循环输出结果。
while(result.hasNext()){
    printjson(result.next())  //用json格式打印结果
}

(3)forEach循环(更加优雅)

const db = connect("company")  //进行链接对应的集合collections
const result = db.workmate.find() //声明变量result,并把查询结果赋值给result
//利用游标的hasNext()进行循环输出结果。
result.forEach(function(result){
    printjson(result)
})

五、索引

1、构造百万级数据,测试索引的威力
//randomInfo.js

//生成随机数
function GetRandomNum(min,max){
    const range = max-min;   //得到随机数区间
    const rand = Math.random(); //得到随机值
    return (min + Math.round(rand *range)); //最小值+随机数取整
}
 
//生成随机用户名
function GetRadomUserName(min,max){
    const tempStringArray= "123456789qwertyuiopasdfghjklzxcvbnm".split("");//构造生成时的字母库数组
    const outPuttext = ""; //最后输出的变量
    //进行循环,随机生产用户名的长度,这里需要生成随机数方法的配合
    for(let i=1 ;i<GetRandomNum(min,max);i++){
        //随机抽取字母,拼装成需要的用户名
        outPuttext=outPuttext+tempStringArray[GetRandomNum(0,tempStringArray.length)]
    }
    return outPuttext;
}

//前提是,创建了company库
const db = connect('company');
const  tempInfo = [];
for (let i=0;i<2000000;i++){
    tempInfo.push({
        username:GetRadomUserName(7,16),
        regeditTime: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),
        randNum8:GetRandomNum(100000,999999),
    })
}
 
db.randomInfo.insert(tempInfo);
print('ok');

//运行脚本,这个过程可能2-3分钟,根据自己的电脑配置不同,会有差别
mongo randomInfo.js

//查看集合的信息,count属性为数据量
db.randomInfo.stats()
2、索引入门

(1)作用
使用已注册索引的字段,进行数据查询,可以高度提升性能

(2)测试普通查询的性能

const startTime = new Date().getTime()  //得到程序运行的开始时间
const db = connect('company')          //链接数据库
const rs = db.randomInfo.find({username:"tfruhjy8k"})  //根据用户名查找用户
rs.forEach(rs=>{printjson(rs)})                     //循环输出
const runTime = new Date().getTime()-startTime;      //得到程序运行时间
print('[SUCCESS]This run time is:'+runTime+'ms')    //打印出运行时间

(3)建立索引

//为username字段,创建索引
//大概需要一分钟左右
db.randomInfo.ensureIndex({username:1})

//查看索引注册列表
db.randomInfo.getIndexes()    //此时存在两个索引,_id是mongoDB的默认索引

(4)存在复合索引的情况,hint()指定优先索引

//优先使用randNum0字段,进行查询(数字索引性能更好)
const rs = db.randomInfo.find({username:'7xwb8y3',randNum0:565509}).hint({randNum0:1});

(5)删除索引

//索引的唯一id,索引注册列表中的name即是
db.randomInfo.dropIndex('randNum0_1');

(6)索引中的小坑

  • 数据不超万条时,不需要使用索引。性能的提升并不明显,而大大增加了内存和硬盘的消耗。
  • 查询数据超过表数据量30%时,不要使用索引字段查询。实际证明会比不使用索引更慢,因为它大量检索了索引表和我们原表。
  • 数字索引,要比字符串索引快的多,在百万级甚至千万级数据量面前,使用数字索引是个明确的选择。
  • 把你经常查询的数据做成一个内嵌数据(对象型的数据),然后集体进行索引。
4、全文索引
//buildText.js
const db = connect('company') 
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."})
db.info.ensureIndex({contextInfo:'text'})    //使用text,代表全文索引

//searchText.js
//$text:使用全文索引,进行查询
//$search:表示搜索关键词
//1、关键词之间,使用空格隔开
//2、不需要搜索的关键词加上‘-’
//3、含空格的词句,使用转义的引号包围
const db = connect('company') 
db.info.find({$text:{$search:"programmer family diary drink"}})
dbd .info.find({$text:{$search:"programmer family diary -drink"}})
db.info.find({$text:{$search:"\"love PlayGame\" drink"}})

六、管理

1、用户的创建、删除与修改

(1)创建root用户

//createRootUser.js
const db = connect('admin')
db.createUser({
    user:"root",
    pwd:"123456",
    roles:[
        {
            role:"root", 
            db:"admin"
        }
    ]
})
//关闭mongodb服务
db.shutdownServer()

//运行脚本
mongo createRootUser.js

内置role分类

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

(2)查找用户信息(有需要再查找)

//用户操作位于admin库进行,下面同理
db.system.users.find()

(3)删除用户(有需要再删除)

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

(4)重启服务器,启动权限模式

mongod --auth

(5)授权

//进入admin库,进行root用户授权操作
use admin

//如果正确返回1,如果错误返回0
//若此时不进行授权,后续将无法操作库
db.auth("root","123456")

(6)为业务使用的库创建用户

//createOtherUser.js
const db = connect('company')
db.createUser({
    user:"tony",
    pwd:"123456",
    roles:[
        {
            role:"readWrite", 
            db:"company"
        }
    ]
})

//运行脚本
mongo createOtherUser.js

PS:admin库设置具有root权限的用户,用于总体管理;业务库设置具有读写权限的用户,用于对业务库操作的权限控制。

2、备份和还原

(1)数据备份

//mongodump基本格式
mongodump
    --host 127.0.0.1
    --port 27017
    --out D:/databack/backup
    --collection myCollections
    --db test
    --username username
    --password password

//备份到 D:/databack/
mongodump --host 127.0.0.1 --port 27017 --out D:/databack/

(2)数据恢复

//mongorestore基本格式
mongorestore
    --host 127.0.0.1
    --port 27017
    --username username
    --password password
    <path to the backup>
//使用 D:/databack/的库,进行数据恢复
mongorestore --host 127.0.0.1 --port 27017 D:/databack/

七、mongoose

1、定义

一个简化mongodb数据库操作的工具。

2、基本操作

(1)连接数据库

const mongoose = require('mongoose')

//监听数据库的连接、断开
mongoose.connection.once('open', () => {
    console.log('connect')
})
mongoose.connection.once('close', () => {
    console.log('disconnect')
})

//连接数据库,域名+端口+数据库名,无端口则使用默认的27017
mongoose.connect('mongodb://127.0.0.1/company', {useNewUrlParser: true})

(2)创建Schema

//创建Schema,用于约束document
const demoSchema = mongoose.Schema({
    name: String,
    age: Number,
    gender: {
        type: Number,
        default: 0
    }
})

(3)创建Model

//创建model,Schema绑定在collection上
const demoModel = mongoose.model('persons', demoSchema)

(4)通过Model,操作数据

//在model中,插入数据,相当于向collection中,插入受约束的document
demoModel.create({
    name: 'tony',
    age: 18
}, err => {
    if(!err) {
        console.log('create_ok!')
    }
})

(5)通过Document,操作数据

3、官网api

相关文章

网友评论

      本文标题:MongoDB教程(入门篇)

      本文链接:https://www.haomeiwen.com/subject/spzifctx.html