# MongoDB

MongoDB是nosql数据库。没有行和列的概念,用JSON键值对来存储数据

集合就相当于“”,文档就相当于“

# 一、基本使用

mongo:连接数据库

show dbs:查看当前数据计算机中的数据库

use DB_name:使用切换到数据库、创建数据库(use 之后才能使用db对象进行操作

db:查看当前所在的数据库

show collections:查看数据库中的表(集合)

# 1】插入数据

db.user.insert({"username":"zhangsan","age":20}):创建user表(集合)以及插入数据

db.user.drop():删除user表(集合)

db.dropDatabase():删除数据库,首先需要use DB_name切换到数据库,才能删除数据库

# 2】查找数据

db.user.find():查找数据库中的user表(集合)中的所有记录

db.user.find({"age":20}):查找user表(集合)中age=20的记录

db.user.find({"age":{$gt:22}}):查找user表(集合)中age>22的记录

db.user.find({"age":{$gte:22}}):查找user表(集合)中age>=22的记录

db.user.find({"age":{$lt:22}}):查找user表(集合)中age<22的记录

db.user.find({"age":{$lte:22}}):查找user表(集合)中age<=22的记录

db.user.find({"age":{$gte:20,$lte:30}}):查找user表(集合)中20<=age<=30的记录

db.user.find({"username":/zhang/}):模糊查找user表(集合)中的记录(正则表达式一致)

db.user.find({},{name:1}):指定列查询数据(第二个参数)只显示name列的记录

db.user.find().sort({age:-1}):排序,1表示升序,-1表示降序

db.user.find().limit(5):查询前5条数据

db.user.find().skip(10):查询10条以后的数据

db.user.find().skip(2).limit(2):查询第3-4条数据(可用于列表分页)

db.user.find().count():查询表中的记录数量(统计数据total)

还可以使用for循环进行造数据:

for(var i=0;i<100;i++){
  db.admin.insert({"username":"wang"+i,"age":i})
}

db.admin.find()//自动进行分页展示,每页20条数据
db.admin.find().count()//100
db.user.find().skip(10).limit(10)//自定义分页展示,pageSize=10,第二页的数据

db.user.find({$or:[{age:22},{age:25}]}):查询age=22或者age=25的记录

db.user.findOne():只查询第一条记录

find查出来是一个数组,findOne查出来是一个对象

# 3】修改数据

前面是查询条件,后面是更新操作($set更新所有匹配的项目),最后是是否开启更新多条记录

db.user.update({"name":"小明"},{$set:{"age":33}},{multi:true}):查找name="小明"的记录,把age改成33并且修改多条查询到的数据

db.user.update({"name":"小明"},{"age":16}):查找name="小明"的记录,全部替换成{"age":16}

# 4】删除数据

db.user.remove({age:132}):删除age=132的数据

db.user.remove({}):删除所有数据

db.user.remove({},{justOne:true}):只删除查找到的第一条数据

# 二、索引基础

设置索引可以优化查询速度,但是插入的速度会变慢。

db.user.find({"username":zhangsan24231}).explain("executionStatus"):查看代码执行信息

# 1】创建索引

db.user.ensureIndex({"username":1}):给user表中的username字段创建一个索引

db.user.ensureIndex({"username":1},{"name":"userindex"}):可以传入第二个参数,给当前设置的索引起别名

# 2】查看表中的索引

db.user.getIndexes():获取user表中的所有索引

# 3】删除索引

db.user.dropIndex({"username":1}):删除user表中的username字段的一个索引

# 4】复合索引

db.user.ensureIndex({"username":1,"age":-1}):数字1表示username键的索引按升序存储,-1表示age键的索引按降序存储。

  • db.user.find({"username":"zhangsan","age":30}):会命中当前复合索引
  • db.user.find({"username":"zhangsan"}):会命中当前复合索引
  • db.user.find({"age":30,"username":"zhangsan"}):不会会命中当前复合索引(如果查询条件中的键值顺序和复合索引中创建顺序不一致,MongoDB会帮我智能调整顺序)
  • db.user.find({"age":30})不会命中当前复合索引(如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列)

# 5】唯一索引

db.user.ensureIndex({"age":1},{"unique":true}):为age键创建唯一索引(age值不能重复)

# 三、权限配置

# 1】创建超级管理员账户(root)

use admin

db.createUser({
  user:'admin',
  pwd:'123456',
  roles:[{role:'root',db:'admin'}]
})

# 2】修改数据库配置文件

修改配置文件,启用权限配置(不管修改什么配置文件都需要备份一下该文件)

//路径:mongoDB\Server\4.0\bin\mongod.cfg

//配置:

security:
		authorization:enabled

# 3】重启mongodb服务

# 4】使用超级管理员账户连接数据库

mongo admin -u 用户名 -p 密码

mongo 192.168.1.200:27017/test -u user -p password

# 5】给eggcms数据库创建一个用户,只能访问eggcms不能访问其他数据库(dbOwner对当前数据库有所有的权限)

use eggcms

db.craeteUser({
  user:'eggadmin',
  pwd:'123456',
  roles:[{role:'dbOwner',db:'eggcms'}]
})

# 6】命令

  • show users:查看当前数据库下的用户
  • db.dropUser('eggadmin'):删除用户
  • db.updateUser('admin',{pwd:'password'}):修改用户密码
  • db.auth('admin','password'):密码认证

# 四、表与表之间关系

  • 一对一
    • 例如:一个人对应一个唯一身份证号,即为一对一的关系
  • 一对多
    • 例如:一个班级对应多名学生,即为一对多的关系
  • 多对多
    • 例如:一个学生可以选多门课程,而同一课程可以被多个学生选修,彼此的对应关系,即是多对多的关系

# 五、聚合管道

aggregation pipeline:使用聚合管道可以对集合中的文档进行变换和组合。(作用:表的关联查询、数据的统计)

MongoDB中使用db.COLLECTION_NAME.aggregate([{<stage>},...])方法来构建和使用聚合管道。先看下官网给的实例,感受一下聚合管道的用法:

在这里插入图片描述

# 1】管道操作符:

$project:增加、删除、重命名字段(对列进行筛选)

$match:条件匹配。只满足条件的文档才能进入下一阶段

$limit:限制结果的数量

$skip:跳过文档的数量

$sort:条件排序

$group:条件组合、统计结果

$lookup:用以引入其它集合的数据(表之间关联查询)

# 2】sql和nosql对比:

SQL NOSQL
WHERE $match
GROUP BY $group
HAVING $match
SELECT $project
ORDER BY $sort
LIMIT $limit
SUM() $sum
COUNT() $sum
JOIN $lookup

# 3】$project

db.order.aggregate([
    {
        $project:{order_id:1, trade_no:1, all_price:1}
        //只显示order_id、trade_no和all_price字段
    }
])

# 4】$match

db.order.aggregate([
    {
        $project:{order_id:1, trade_no:1, all_price:1}
        //管道1:筛选需要的字段
    },
    {
        $match:{all_price:{$gte:90}}
        //(all_price>=90)管道2:查询条件
    }
])

# 5】$group

db.order.aggregate([
    {
        $group:{id:"$order_id", total:{$sum:"$num"}}
        //以order_id进行分组,再将相同的id的num字段进行求和
    }
])

# 6】$sort

db.order.aggregate([
    {
        $sort:{all_price:-1}
        //将数据以all_price字段进行排序:-1表示降序,1表示升序
    }
])

# 7】$limit

db.order.aggregate([
    {
        $limit:1
        //限制输出的数据条数(结合$skip进行分页查询操作)
    }
])

# 8】$skip

db.order.aggregate([
    {
        $skip:1
        //跳过第一条数据,进行数据展示
    }
])

# 9】$lookup

表关联:

db.order.aggregate([//在order表中进行管道操作(主表)
    {
        $lookup:{//关联表查询
            from:"order_item",//需要关联的表是:order_item(非主表)
            localField:"order_id",//order表(主表)中需要关联的字段
            foreignField:"order_id",//order_item(非主表)中需要关联的字段
            as:"items"//关联查询后把order_item(非主表)对应结果放到order表(主表)的items字段中
        }
    }
])
//[{order_id:1, trade_no:007, items:[{order_id:1,title:'书包'},{order_id:1,title:'笔记本'}]},{order_id:2, trade_no:007, items:[{order_id:2,title:'笔'}]}]

# 六、备份与还原

#备份
mongodump -h dbhost -d dbname -o dbdirectory
mongodump -h 127.0.0.1 -d orders -o D:\backup\db

-h:mongoDB所在服务器地址,例如:127.0.0.1当然也可以指定端口号127.0.0.1:27017
-d:需要备份的数据库实例,例如:test
-o:备份的数据存放位置,例如:/home/mongodump/,当然该目录需要提前建立,这个目录里面存放数据库实例的备份数据。

#还原
mongorestore -h dbhost -d dbname dbdirectory
mongorestore -h 127.0.0.1 -d orders D:\backup\db

-h:mongoDB所在服务器地址
-d:需要备份的数据库实例,例如:test,当然这个名称也可以和备份的时候不一样,比如test2

# nodejs操作mongoDB数据库

# 1】新建项目安装依赖

#新建项目
mkdir mongoproject
cd mongoproject
#创建npm
npm init
#安装依赖
npm install mongodb --save

# 2】引入模块

//app.js
const { MongoClient } = require('mongodb')
//连接url
const url = 'mongodb://localhost:27017';
//数据库名
const dbName = 'mongoproject'
//创建mongo服务
const client = new MongoClient(url, { useUnifiedTopology: true });
//使用连接方法连接服务
client.connect(function (err) {
    if (err) return
    console.log('数据库连接成功');
    const db = client.db(dbName);
    //返回的db对象进行数据库的操作

    //1、查找数据
    db.collection('orders')
        .find({}).toArray((err, data) => {
        if (err) return
        console.log(data)
        //异步操作,操作数据库完毕以后一定要 关闭数据库连接
        client.close()
    })
    
    //2、增加数据
    db.collection('orders')
        .insertOne(
        { 'orderId': '000', 'name': 'order1' }, 
        (err, result) => {
            if (err) return
            console.log('增加成功', result.insertedId)
            client.close()
        })
    
    //3、修改数据
    db.collection('orders')
        .updateOne(
        { 'orderId': '000' },
        { $set: { "name": 'order2' } }, 
        (err, result) => {
            if (err) return
            console.log('修改成功', result)
            client.close()
        })
    
    //4、删除一条数据
    db.collection('orders')
        .deleteOne(
        { 'orderId': '000' }, 
        (err, result) => {
            if (err) return
            console.log('删除一条数据成功', result)
            client.close()
        })
    
    //5、删除多条数据
    db.collection('orders')
        .deleteMany(
        { 'orderId': '000' },
        (err, result) => {
            if (err) return
            console.log('删除多条数据成功', result)
            client.close()
        })
    
})

# 3】在node服务中连接数据库

每次请求都是用的相同的实例client

const http = require('http')
const app = require('./module/route')

const { MongoClient } = require('mongodb')
const url = 'mongodb://localhost:27017'
const dbName = 'rayhomie'
//此时,每次请求都是用的相同的实例client
const client  = new MongoClient(url, { useUnifiedTopology: true })

//注册web服务
http.createServer(app).listen(3000);
//配置路由
app.get('/',(req,res)=>{
  client.connect((err)=>{
    if(err){
      console.log(err);
      return;
    }
    const db =client.db(dbName)
    
    //查询数据
    db.collection('user').find({}).toArray((err,data)=>{
      if(err) return;
      console.log(data)
      client.close()//操作数据库之后一定要关闭连接
      res.send(data)
    })
  })
})

每次请求都创建新的client实例

const http = require('http')
const app = require('./module/route')

const { MongoClient } = require('mongodb')
const url = 'mongodb://localhost:27017'
const dbName = 'rayhomie'

//注册web服务
http.createServer(app).listen(3000);
//配置路由
app.get('/',(req,res)=>{
  //每次请求都会重新创建新的实例
  MongoClient.connect(url,(err,client)=>{
     if(err){
      console.log(err);
      return;
    }
    const db =client.db(dbName)
    
    //查询数据
    db.collection('user').find({}).toArray((err,data)=>{
      if(err) return;
      console.log(data)
      client.close()//操作数据库之后一定要关闭连接
      res.send(data)
    })
  })
})
Last Updated: 8/1/2021, 1:43:20 PM