const koa =require('koa')
const bodyParser =require('koa-bodyparser')
const Router =require('koa-router')
const mongodb =require('mongodb')
let dbc,company=null
mongodb.MongoClient.connect('mongodb://localhost:27017/',(err,db)=>{
if(err)throw err
console.log('数据库连接成功')
dbc=db
company=dbc.db('company')
})
const user=new Router()
const router=new Router()
user
.get('/name',async (ctx,next)=>{
let oQuery=ctx.request.query
if(oQuery.name){
let persons=await (()=>{
return new Promise((resolve,reject)=>{
company.collection('workmate').find({name:oQuery.name}).toArray((err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
//查找嵌入式文档 db.workmate.find({"skill.skillOne":"HTML+CSS"})
.get('/namebyskill',async (ctx,next)=>{
let oQuery=ctx.request.query
if(oQuery){
let persons=await (()=>{
let skill=JSON.parse(oQuery.skill)
let keys=Object.keys(skill)
let w=`skill.${keys[0]}`
return new Promise((resolve,reject)=>{
//结果显示 修改无效
company.collection('workmate').find({[w]:skill[keys[0]]},{name:true,age:true,'skill.skill1':true}).toArray((err,res)=>{
if(err){
reject(err)
}else{
delete res[0]._id
delete res[0].register
resolve(res)
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
//查找嵌入式文档 db.workmate.find({"skill.skillOne":"HTML+CSS"})
.get('/range',async (ctx,next)=>{
let oq=ctx.request.query
if(oq.min&&oq.max){
let persons=await (()=>{
return new Promise((resolve,reject)=>{
//结果显示 修改无效
company.collection('workmate').find({age:{$lte:Number(oq.max),$gte:Number(oq.min)}},{name:true,age:true,'skill.skill1':true}).toArray((err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
//更新部分对象下的数据数据
.put('/skill',async (ctx,next)=>{
let bodyData=ctx.request.body
if(bodyData.skill!=0&&bodyData.name){
let persons=await (()=>{
let skill={}
return new Promise((resolve,reject)=>{
company.collection('workmate').find({name:bodyData.name}).toArray((err,res)=>{
if(err){
reject(err)
}else{
skill=res[0].skill
skill=Object.assign(skill,JSON.parse(bodyData.skill))
console.log(skill)
company.collection('workmate').updateOne({name:bodyData.name},{$set:{skill}},(err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
.delete('/age',async (ctx,next)=>{
let bodyData=ctx.request.body
if(bodyData.key&&bodyData.name){
let persons=await (()=>{
return new Promise((resolve,reject)=>{
// $unset 删除某个属性 只在乎key值 $unset:{key:""}
company.collection('workmate').updateOne({name:bodyData.name},{$unset:{[bodyData.key]:''}},(err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
//添加和修改键值对
.post('/key',async (ctx,next)=>{
let bodyData=ctx.request.body
if(bodyData.key&&bodyData.name){
let persons=await (()=>{
return new Promise((resolve,reject)=>{
company.collection('workmate').updateOne({name:bodyData.name},{$set:JSON.parse(bodyData.key)},(err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
//全部添加key值
.post('/keys',async (ctx,next)=>{
let bodyData=ctx.request.body
if(bodyData.key){
let persons=await (()=>{
return new Promise((resolve,reject)=>{
console.log(bodyData.key)
company.collection('workmate').updateMany({},{$set:JSON.parse(bodyData.key)},{multi:true},(err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
//全部添加key值 同上面啊的效果是一样的
.post('/keys2',async (ctx,next)=>{
let bodyData=ctx.request.body
if(bodyData.key){
let persons=await (()=>{
return new Promise((resolve,reject)=>{
console.log(bodyData.key)
company.collection('workmate').updateMany({},{$set:JSON.parse(bodyData.key)},(err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
// {$set:{age:20}},{upsert:true} 修改数据 没有就添加
//$inc 修改相对 加减
.put('/age',async (ctx,next)=>{
let bodyData=ctx.request.body
if(bodyData.ageAmount&&bodyData.name){
let persons=await (()=>{
return new Promise((resolve,reject)=>{
company.collection('workmate').updateOne({name:bodyData.name},{$inc:{age:Number(bodyData.ageAmount)}},(err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
}else{
ctx.status=400
ctx.body={success:false,message:'参数错误'}
}
await next()
})
//数组 $push:{interest:'game'}添加 是否存在 interest:{$ne:'game'}
// db.workmate.update({name:'xiaoWang',"interest":{$ne:'playGame'}},{$push:{interest:'Game'}}) 前面查找 后面是添加 如果不存在再执行操作,存在就不执行
// db.workmate.update({name:"xiaoWang"},{$addToSet:{interest:"readBook"}})它是$ne的升级版本(查找是否存在,不存在就push上去
// var newInterset=["Sing","Dance","Code"];
// db.workmate.update({name:"xiaoWang"},{$addToSet:{interest:{$each:newInterset}}})
// db.workmate.update({name:'xiaoWang'},{$pop:{interest:1}}) 1:从数组末端进行删除 -1:从数组开端进行删除
.get('/lists',async (ctx,next)=>{
let oQuery=ctx.request.query
if(!oQuery.page){
ctx.status=400
ctx.body={success:false,message:'请传入page'}
}
let skipTip=Number(oQuery.page)*8
let persons=await (()=>{
return new Promise((resolve,reject)=>{
company.collection('workmate').find().sort({name:-1}).skip(skipTip).limit(8).toArray((err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
await next()
})
.post('/lists',async(ctx,next)=>{
let d=[]
for(let i=0;i<49;i++){
let data={
"name":"王榕"+i,
"skill":{
"skill1":"ppt"
},
"register":1530088530369,
"age":23
}
d.push(data)
}
let persons=await (()=>{
return new Promise((resolve,reject)=>{
company.collection('workmate').insertMany(d,(err,res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
})()
ctx.body=persons
await next()
})
/*
db.workmate.find(
{
$or:[
{age:{
$in:[27,28]
}},
{name:'王榕22'}
]
},
{
_id:0,
name:1,
age:1
}
)
{ "name" : "王榕22", "age" : 27 }
{ "name" : "王榕24", "age" : 28 }
{ "name" : "王榕22", "age" : 23 }
数组 完全匹配
{ "_id" : ObjectId("5b347bf2c44e54f671158958"), "name" : "we", "interest" : [ "fe", "f" ] }
> db.wokers.find({interest:['fe','a']})
> db.wokers.find({interest:['fe','f','a']})
{ "_id" : ObjectId("5b347bffc44e54f671158959"), "name" : "we2", "interest" : [ "fe", "f", "a" ] }
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "interest" : [ "fe", "f", "a" ] }
{ "_id" : ObjectId("5b347c0cc44e54f67115895b"), "name" : "we4", "interest" : [ "fe", "f", "a" ] }
单项查询 存在即匹配
> db.wokers.find({interest:'fe'})
{ "_id" : ObjectId("5b347bf2c44e54f671158958"), "name" : "we", "interest" : [ "fe", "f" ] }
{ "_id" : ObjectId("5b347bffc44e54f671158959"), "name" : "we2", "interest" : [ "fe", "f", "a" ] }
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "interest" : [ "fe", "f", "a" ] }
{ "_id" : ObjectId("5b347c0cc44e54f67115895b"), "name" : "we4", "interest" : [ "fe", "f", "a" ] }
{ "_id" : ObjectId("5b347c19c44e54f67115895c"), "name" : "we3", "interest" : [ "fe", "b", "a" ] }
数组部分匹配 包含都有
> db.wokers.find({interest:{$all:['a','b']}})
{ "_id" : ObjectId("5b347c19c44e54f67115895c"), "name" : "we3", "interest" : [ "fe", "b", "a" ] }
数组部分 包含 其中一个
> db.wokers.find({interest:{$in:['a','b']}})
{ "_id" : ObjectId("5b347bffc44e54f671158959"), "name" : "we2", "interest" : [ "fe", "f", "a" ] }
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "interest" : [ "fe", "f", "a" ] }
{ "_id" : ObjectId("5b347c0cc44e54f67115895b"), "name" : "we4", "interest" : [ "fe", "f", "a" ] }
{ "_id" : ObjectId("5b347c19c44e54f67115895c"), "name" : "we3", "interest" : [ "fe", "b", "a" ] }
数组长度 定数2
> db.wokers.find({interest:{$size:2}})
{ "_id" : ObjectId("5b347bf2c44e54f671158958"), "name" : "we", "interest" : [ "fe", "f" ] }
结果数组处理 $slice 1:正数 -1:倒数 数组 第0个到2个 第一个是1不包含开始
> db.wokers.find({interest:{$size:2}},{interest:{$slice:[0,2]}})
{ "_id" : ObjectId("5b347bf2c44e54f671158958"), "name" : "we", "interest" : [ "fe", "f" ] }
> db.wokers.find({interest:{$size:2}},{interest:{$slice:1}})
{ "_id" : ObjectId("5b347bf2c44e54f671158958"), "name" : "we", "interest" : [ "fe" ] }
> db.wokers.find({interest:{$size:2}},{interest:{$slice:-1}})
{ "_id" : ObjectId("5b347bf2c44e54f671158958"), "name" : "we", "interest" : [ "f" ] }
// 参数1 条件 参数2 显示结果 limit()限制条目 skip()跳过条目sort排序 整数正序 负数 倒序
> db.wokers.find({},{name:1,age:1}).limit(2).skip(0).sort({age:-1})
{ "_id" : ObjectId("5b347c0cc44e54f67115895b"), "name" : "we4", "age" : 36 }
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "age" : 26 }
// 参数1 条件 参数2 显示结果 limit()限制条目 skip()跳过条目sort排序 整数正序 负数 倒序
> db.wokers.find({},{name:1,age:1}).limit(2).skip(2).sort({age:-1})
{ "_id" : ObjectId("5b347c19c44e54f67115895c"), "name" : "we5", "age" : 26 }
{ "_id" : ObjectId("5b347bffc44e54f671158959"), "name" : "we2", "age" : 25 }
*/
/*
> db.workmate.find({$and:[{age:{$in:[27,28]}},{name:'王榕22'}]},{_id:0,name:1,age:1})
{ "name" : "王榕22", "age" : 27 }
索引:构造百万级数据
快,但是消耗内存和硬盘
//获取 workers 集合 详情
> db.wokers.stats()
{
"ns" : "company.wokers",
"size" : 450,
"count" : 5,
"avgObjSize" : 90,
"storageSize" : 36864,
"capped" : false,
索引:只有一条索引 _id 自动生成 很少使用
1.数据不超过万条
2.查询数据超过30%,不要索引 不快反而慢 性别 技术工种
3.数字索引比字符串索引快
4.把你经常查询的数据做成一个内嵌数据(对象型的数据),然后集体进行索引。
只有64 个索引 mongo
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "company.wokers"
}
]
// 建立索引
> db.wokers.ensureIndex({name:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
// 两个索引
> db.wokers.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "company.wokers"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "name_1",
"ns" : "company.wokers"
}
]
复合索引:
在建一个索引
> db.wokers.ensureIndex({idNum:1})
索引顺序
按获取的索引 顺序下来 以前是数字 再 字母
hint方法 指明优先使用的索引
> db.wokers.find({name:'we3',idNum:'idofe90'}).hint({idNum:1})
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "interest" : [ "fe", "f", "a" ], "age" : 26, "idNum" : "idofe90" }
删除索引
db.wokers.dropIndex('idNum_1') //使用的是索引对应的name属性
{ "nIndexesWas" : 3, "ok" : 1 }
> db.wokers.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "company.wokers"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "name_1",
"ns" : "company.wokers"
}
]
全文索引:
1.建立全文索引
> db.wokers.ensureIndex({contentinfo:'text'})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
2.
{
"v" : 2,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "contentinfo_text",//name 不一样的
"ns" : "company.wokers",
"weights" : {
"contentinfo" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
全文索引查找
为什么只能找英文
> db.wokers.find({$text:{$search:'btr'}})
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "interest" : [ "fe", "f", "a" ], "age" : 26, "idNum" : "idofe90", "contentinfo" : "few wefw fwewe f i am btr ambtr" }
> db.wokers.find({$text:{$search:'wefw'}})
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "interest" : [ "fe", "f", "a" ], "age" : 26, "idNum" : "idofe90", "contentinfo" : "few wefw fwewe f i am btr ambtr" }
{ "_id" : ObjectId("5b347bffc44e54f671158959"), "name" : "we2", "interest" : [ "fe", "f", "a" ], "age" : 25, "idNum" : "idofe90", "contentinfo" : "aw wefw fwewe f i am btr ambtr" }
> db.wokers.find({$text:{$search:'few'}})// 不知道为什么找不到这里
> db.wokers.find({$text:{$search:'wefw -aw'}}) - 表示排除
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "interest" : [ "fe", "f", "a" ], "age" : 26, "idNum" : "idofe90", "contentinfo" : "few wefw fwewe f i am btr ambtr" }
> db.wokers.find({$text:{$search:'wefw aw'}}) 空格表示或的关系
{ "_id" : ObjectId("5b347bffc44e54f671158959"), "name" : "we2", "interest" : [ "fe", "f", "a" ], "age" : 25, "idNum" : "idofe90", "contentinfo" : "aw wefw fwewe f i am btr ambtr" }
{ "_id" : ObjectId("5b347c06c44e54f67115895a"), "name" : "we3", "interest" : [ "fe", "f", "a" ], "age" : 26, "idNum" : "idofe90", "contentinfo" : "few wefw fwewe f i am btr ambtr" }
>
转义字符
> db.wokers.find({$text:{$search:'\"aw wefw\"'}})
{ "_id" : ObjectId("5b347bffc44e54f671158959"), "name" : "we2", "interest" : [ "fe", "f", "a" ], "age" : 25, "idNum" : "idofe90", "contentinfo" : "aw wefw fwewe f i am btr ambtr" }
得到混合的 连着的字符串查找 而不是 两个单独的 单词
用户权限部分:
我们默认开了一个最高管理权限方便我们管理数据库
能用mongo表示最高权限用户
用户的数据库
> use admin
switched to db admin
> show collections
system.version
创建角色:
db.createUser({
user:'useradmin',//用户名
pwd:'123456',//密码
customData:{//管理员信息
name:'user管理',
email:'[email protected]',
age:12
},
roles:[{//用户对于不同数据的 权限
role:'readWrite',//read readWrite
db:'user'
},
'read'//其他数据库
]
})
Successfully added user: {
"user" : "useradmin",
"customData" : {
"name" : "user管理",
"email" : "[email protected]",
"age" : 12
},
"roles" : [
{
"role" : "readWrite",
"db" : "user"
},
"read"
]
}
> show collections
system.users//添加了用户就有的集合
system.version
> db
admin
> db.system.users.find()
{ "_id" : "admin.useradmin", "user" : "useradmin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "mCJGHoxiiPFWACspHUtUkg==", "storedKey" : "NJZktblBzkMvSRpYNCNIHzHNxH4=", "serverKey" : "gTGUAyyUVKGoXy/gwApbmo2Zx2M=" } }, "customData" : { "name" : "user管理", "email" : "[email protected]", "age" : 12 }, "roles" : [ { "role" : "readWrite", "db" : "user" }, { "role" : "read", "db" : "admin" } ] }
删除用户
> db.system.users.remove({user:'useradmin'})
WriteResult({ "nRemoved" : 1 })
建权:
用户登录 不再直接 通过 mongo 连接 最高权限 而是通过一个 有设定权限的账号
> db.auth('useradmin','123456') 账号密码 登录
1//成功
重启服务》数据库服务 表示需要权限了
C:\data>mongod --auth
再试试用 mongo 连接
C:\Users\admin>mongo
MongoDB shell version v3.6.5
connecting to: mongodb://127.0.0.1:27017 //为啥还是能连接到数据库呢 不是强制关闭么
MongoDB server version: 3.6.5
> show dbs //命令返回没有权限
2018-06-29T09:20:21.375+0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not authorized on admin to execute command { listDatabases: 1.0, $db: \"admin\" }",
"code" : 13,
"codeName" : "Unauthorized"
} :
使用鉴权用户登录
就是我们之前建立的账户
C:\Users\admin>mongo -u useradmin -p 123456 127.0.0.1:27017/admin
MongoDB shell version v3.6.5
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 3.6.5
错误
C:\Users\admin>mongo -u useramdin 123456 127.0.0.1:27017/admin
MongoDB shell version v3.6.5
Enter password:
connecting to: mongodb://127.0.0.1:27017/123456
MongoDB server version: 3.6.5
2018-06-29T09:25:53.983+0800 E QUERY [thread1] Error: Authentication failed. :
DB.prototype._authOrThrow@src/mongo/shell/db.js:1608:20
@(auth):6:1
@(auth):1:2
exception: login failed
有权限 正常操作
> use user
switched to db user
> show collections
user
> db.user.find()
{ "_id" : ObjectId("5b31ffa5868b4e3aa9ead2ff"), "name" : "few" }
无权限 报 13
> use company
switched to db company
> show collections
2018-06-29T09:28:02.262+0800 E QUERY [thread1] Error: listCollections failed: {
"ok" : 0,
"errmsg" : "not authorized on company to execute command { listCollections: 1.0, filter: {}, $db: \"company\" }",
"code" : 13,
"codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype._getCollectionInfosCommand@src/mongo/shell/db.js:941:1
DB.prototype.getCollectionInfos@src/mongo/shell/db.js:953:19
DB.prototype.getCollectionNames@src/mongo/shell/db.js:964:16
shellHelper.show@src/mongo/shell/utils.js:842:9
shellHelper@src/mongo/shell/utils.js:739:15
@(shellhelp2):1:1
数据库备份
没有备份权限
C:\Users\admin>mongodump --host 127.0.0.1 --port 27017 --out D:/backup/ --collection user --db user --username useradmin --password 123456
2018-06-29T09:53:44.495+0800 Failed: error connecting to db server: server returned error on SASL authentication step: Authentication failed.
重启服务 使用 最高权限
mongod
C:\Users\admin>mongodump --host 127.0.0.1 --port 27017 --out D:/backup/
2018-06-29T09:56:44.501+0800 writing admin.system.users to
2018-06-29T09:56:44.572+0800 done dumping admin.system.users (1 document)
2018-06-29T09:56:44.572+0800 writing admin.system.version to
2018-06-29T09:56:44.576+0800 done dumping admin.system.version (2 documents)
2018-06-29T09:56:44.576+0800 writing log.test to
2018-06-29T09:56:44.576+0800 writing log.login to
2018-06-29T09:56:44.577+0800 writing company.workmate to
2018-06-29T09:56:44.577+0800 writing company.wokers to
2018-06-29T09:56:44.584+0800 done dumping log.login (2 documents)
2018-06-29T09:56:44.584+0800 writing user.user to
2018-06-29T09:56:44.592+0800 done dumping company.workmate (101 documents)
2018-06-29T09:56:44.593+0800 done dumping log.test (1000 documents)
2018-06-29T09:56:44.593+0800 done dumping company.wokers (6 documents)
2018-06-29T09:56:44.593+0800 done dumping user.user (1 document)
输出备份文件中 json后缀是描述 bson是数据
恢复文件
C:\Users\admin>mongorestore --host 127.0.0.1 --port 27017 D:/backup/
> show dbs
admin 0.000GB
company 0.000GB
config 0.000GB
local 0.000GB
log 0.000GB
user 0.000GB
数据库已经恢复
图形化界面
https://robomongo.org/download
*/
const app=new koa()
router
.use('/user',user.routes(),user.allowedMethods())
app
.use(bodyParser())
.use(router.routes())
.use(router.allowedMethods())
app.listen(3002,()=>{
console.log('run')
})