MongoDB

MongoDB


MongoDB是一个基于分布式文件存储的非关系型数据库

MongoDB文档是一个键值对(即BSON),文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库区别很大,也是MongoDB的特点



MongoDB的概念


SQL概念MongoDB概念说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primary keyprimary key主键约束,MongoDB自动将_id字段设置为主键

MongoDB的数据类型


数据类型描述
String字符串,存储数据常用的数据类型,在MongoDB中UTF-8才合法
Integer整型数值,用于存储数值(32或64)
Boolean布尔值
Double双精度浮点值
Min/Max keys将一个值与BSON(二进制JSON)元素的最低值和最高值相对比
Arrays用于将数组或列表或多个值存储为一个键
Timestamp时间戳,记录文档修改或添加的具体时间
Object用于内嵌文档
Null用于创建空值
Symbol符号,基本等同于字符串类型,但一般用于采用特殊符号型语言
Date时间日期,用UNIX时间格式存储时间或日期
Object ID对象ID 用于创建文档的ID
Binary Data二进制数据
Code代码类型,存储javascript代码
Regular expression正则表达式类型,用于存储正则表达式



MongoDB启动方式


方式1 命令行

cd 到安装MongoDB的文件夹下的bin文件夹 
运行 mongod --dbpath 数据库文件夹

此时出现端口号"port":27017即启动成功

MongoDB starting","attr":{"pid":17048,"port":27017,"dbPath":"D:/mongodb/db","architecture":"64-bit","host":"ABHR1WSUJ6HWMZT"}}

再打开终端操作即可(这个启动MongoDB的终端不能停止)

方式2 配置文件

在目录下新建config文件夹,该文件夹中新建配置文件mongod.conf

storage:
  #The directory where the mongod instance stores its data.Default Value is "\data\db" on Windows.
  dbPath: D:\02_Server\DBServer\mongodb-win32-x86_64-2008plus-ssl-4.0.1\data (自己的数据库路径)

然后启动

mongod -f ./config/mongod.conf
或
mongod --config ../config/mongod.conf (自己的配置文件)



MongoDB连接

连接本机数据库

mongo

连接远程数据库

mongo 127.0.0.1:27017




MongoDB操作


数据库操作

db #查询当前数据库

show dbs #查询所有数据库

use music #创建/切换数据库

db.dropDataBase() #删除数据库

集合操作

db.createCollection('collectionName') #创建一个集合

db.getCollectionNames() #得到当前db的所有集合

文档操作

1.插入数据
#baoguo为创建的集合名

#插入数据
db.baoguo.insert([{name: 'm1', release: '2020-12-05'}])  

#可同时插入多个
db.baoguo.insert([{name: 'm2', release: '2020-12-05'}, {name: 'm3', release: '2020-12-06'}]) 

#insert或save都可以实现 
db.baoguo.save([{name: 'm4', release: '2020-12-07'}, {name: 'm5', release: '2020-12-08'}])

db.baoguo.insert([{name: 'm1', release: '2020-12-05', publishNum: 100}])
2.修改数据
#set 覆盖式修改 第一个参数为条件 第二个参数为需要修改的值
db.baoguo.update({name: 'm1'}, {$set: {release: '2020-12-04'}})

#inc 增量式修改 第一个参数为条件 第二个参数为对应属性的增加值
db.baoguo.update({name: 'm100'}, {$inc: {publishNum: 100}})

#第三个参数为如果没有相应数据时是否创建新的数据
db.baoguo.update({name: 'm1000'}, {$inc: {publishNum: 200}},true)

#第四个参数为是否全部匹配,默认只匹配修改一个
db.baoguo.update({name: 'm1'}, {$inc: {publishNum: 200}},true,true)
3.删除数据
#参数为条件
db.baoguo.delete({name: 'm1000'}) 
4.查询数据

条件查询

#查询baoguo下所有数据
db.baoguo.find() 

#查询baoguo下的name去重后的数据
db.baoguo.distinct('name') 

#查询baoguo下的release为'2020-12-05'的数据
db.baoguo.find({release: '2020-12-05'}) 

判断查询

#查询baoguo下的release大于'2020-12-05'的数据 (gt大于)
db.baoguo.find({release: {$gt: '2020-12-05'}}) 

#查询baoguo下的release大于等于'2020-12-05'的数据 (gte大于等于)
db.baoguo.find({release: {$gte: '2020-12-05'}}) 

#查询baoguo下的release小于'2020-12-05'的数据 (lt小于)
db.baoguo.find({release: {$lt: '2020-12-05'}}) 

#查询baoguo下的release小于等于'2020-12-05'的数据 (lte小于等于)
db.baoguo.find({release: {$lte: '2020-12-05'}}) 

#查询baoguo下的release大于等于'2020-12-04'且小于等于'2020-12-06'的数据 (组合判断)
db.baoguo.find({release: {$gte: '2020-12-04', $lte: '2020-12-06'}}) 

#查询baoguo下的release为'2020-12-04'或'2020-12-05'的数据 
db.baoguo.find({$or:[{release: '2020-12-04'}, {release: '2020-12-05'}]}) 

正则匹配

#查询baoguo下的name为1开头的数据
db.baoguo.find({name:/^1/}) 

#查询baoguo下的name为1结尾的数据
db.baoguo.find({name:/1$/}) 

#查询baoguo下除_id和publishNum以外的数据
db.baoguo.find({},{_id: 0, publishNum: 0}) 

#查询baoguo下的除_id和publishNum以外的且name以1结尾的数据
db.baoguo.find({name:/1$/}, {_id: 0, publishNum: 0}) 

sort排序 skip跳过 limit截取个数

#查询baoguo下的所有数据并按照release的升序排序
db.baoguo.find().sort({release: 1})

#查询baoguo下的所有数据并按照release的降序排序
db.baoguo.find().sort({release: -1})

#查询baoguo下的数据并按照release的升序排序,跳过6个截取3个数据
db.baoguo.find().sort({release: 1}).limit(3).skip(6)

#sort方法的位置并不影响最后结果,先排序后截取 ↑
db.baoguo.find().limit(3).skip(6).sort({release: 1})

其他

#查询baoguo下的第一个数据
db.baoguo.findOne()

#查询baoguo下的数据个数
db.baoguo.find().count()



基于node的mongodb增删改查


node连接mongodb

mongodb版本号需为2.x
"mongodb": "^2.3.1"

const MongoClient = require('mongodb').MongoClient
const ObjectId = require('mongodb').ObjectId

// 数据库地址 /后为连接数据库名称
const url = 'mongodb://localhost:27017/meizu'

MongoClient.connect(url, function (err, db) {
    if (err) {
      console.log('连接数据库失败');
      return
    } else {
      db.collection('表名').insertOne({
        //键: 值, (没引号)-- 需要插入的数据
      }, (error, result) => {
        if (error) {
          console.log('失败');
          return
        } else {
          console.log('成功');
          res.send(result)
          db.close()
        }
      })
    }
  })

MongoClient.connect(url, function (err, db) {
    if (err) {
      console.log('连接数据库失败');
      return
    } else {
      db.collection('表名').deleteOne({
        //键: 值, (没引号)--条件  删除符合条件的项
      }, function (error, data) {
        if (error) {
          console.log('删除失败');
          return
        } else {
          console.log(data);
          res.send('删除成功')
          db.close()
        }
      })
    }
  })

 MongoClient.connect(url, function (err, db) {
    if (err) {
      console.log('连接数据库失败');
      return
    } else {
      db.collection('表名').updateOne({
        //键: 值, (没引号)--条件  更新符合条件的项
      }, {
        $set: {
          //'键': 值, --需要更新的值
        }
      }, (error, result) => {
        if (error) {
          console.log('失败');
          return
        } else {
          console.log('成功');
          res.send(result)
        }
      })
    }
  })

 MongoClient.connect(url, function (err, db) {
    if (err) {
      console.log('连接数据库失败');
      return
    } else {
      const result = db.collection('表名').find()
      const list = []   //获取到结果为文档 
      result.each((error, doc) => { //需要each方法遍历后的元素才是查询出来的数据
        if (error) {
          console.log(error);
        } else {
          if (doc != null) {    
            list.push(doc)		// 遍历不为空则没遍历完 插入到数组中
          } else {
            res.send(list);		//如果为空则文档中数据遍历完 返回数组
            db.close()
          }
        }
      })
    }
  })




数据库导入导出


MongoDB数据库备份

mongodump -h dbhost -d dbname -o dbdirectory

参数说明:

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

eg:

sudo rm -rf /home/momgodump/
sudo mkdir -p /home/momgodump
sudo mongodump -h 192.168.17.129:27017 -d itcast -o /home/mongodump/



MongoDB数据库恢复

 mongorestore -h dbhost -d dbname --dir dbdirectory

参数说明:

-h: MongoDB所在服务器地址
-d: 需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
–dir: 备份数据所在位置,例如:/home/mongodump/itcast/
–drop: 恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用!

eg:

 mongorestore -h 192.168.17.129:27017 -d itcast_restore --dir /home/mongodump/itcast/




Mongoose


Mongoose为模型提供了一种直接的,基于scheme结构去定义你的数据模型。

它内置数据验证, 查询构建,业务逻辑钩子等



Mongoose连接Mongodb数据库

// 创建db.js用于连接Mongodb数据库 

// 先引入mongoose模块 这个模块是为了便于对mongodb进行操作的一个类库
const mongoose = require('mongoose')

// 连接数据库服务器
// mongodb:// 协议头
// 127.0.0.1 mongodb服务器的地址
// 27017 mongodb的端口
// bus 数据库名称

mongoose.connect('mongodb://127.0.0.1:27017/bus', {
  useNewUrlParser: true,
  useUnifiedTopology: true
}, function (error) {
  if (error) {
    console.log('数据库连接失败')
  } else {
    console.log('数据库连接成功')
  }
})

module.exports = mongoose



创建集合模型

// model文件夹下创建一个集合模型 collection.js

// collection
const mongoose = require('mongoose')

// 需要在使用mongoose.Scheme 对于这个表的对应指定进行声明
const Scheme = mongoose.Schema({  // 数据集合的表头
  userName: String,   // 用户名
  phone: String,      // 用户电话
  addres: String,     // 用户住址
  Uid: String,        // 用户身份证号码
  pwd: String,        // 用户密码
  sex: Number,        // 用户性别
  status: Number      // 用户注册状态
},{
  timestamps:true     // 设置为true会自动添加及维护两个字段 createAt updateAt
})

const collection = mongoose.model('user', Scheme)

module.exports = collection



Mongoose操作

// 引入对应文件

const app = require('express')()   		// 引入express
const db = require('./db')				// 引入Mongoose数据库连接 不需要调用 引入即可
const user = require('./collection')	// 引入Mongoose集合模型

Mongoose增加数据
// 增
// model.create({...})  增加一个数据
app.use('/add', async (req, res) => {
  const u = await user.create({
   	// key:value
  })
  res.send({
    success: true,
    data: u
  })
})

Mongoose删除数据
// 删
// model.deleteOne({...}) 删除一个数据
app.use('/delete', async (req, res) => {
  const u = await user.deleteOne({
    // key:value 删除的条件
  })
  res.send({
    success: true,
    data: u
  })
})

// model.deleteMany({...}) 删除多个数据
app.use('/deleteall', async (req, res) => {
  const u = await user.deleteMany({
    // key:value 删除的条件
  })
  res.send({
    success: true,
    data: u
  })
})

// model.findByIdAndDelete(' id ') 按id删除数据
app.use('/deleteid', async (req, res) => {
  const u = await user.findByIdAndDelete(' 数据id ')
  res.send({
    success: true,
    data: u
  })
})


Mongoose修改数据
// 改
// model.updateOne({...},{...}) 修改一个数据
app.use('/updateone', async (req, res) => {
  const u = await user.updateOne({
    // key:value 修改的条件
  }, {
   	// key:value 需要修改的键和值
  })
  res.send({
    success: true,
    data: u
  })
})

// model.updateMany({...},{...}) 修改多个数据
app.use('/updateall', async (req, res) => {
  const u = await user.updateMany({
    // key:value 修改的条件
  }, {
   	// key:value 需要修改的键和值
  })
  res.send({
    success: true,
    data: u
  })
})

// model.findByIdAndUpdate(' 数据id ', {...})
app.use('/updateid', async (req, res) => {
  const u = await user.findByIdAndUpdate(' 数据id ', {
    // key:value 需要修改的键和值
  })
  res.send({
    success: true,
    data: u
  })
})


Mongoose查找数据
// 查
// model.findById(' 数据id ')  通过id搜索数据
app.use('/findid', async (req, res) => {
  const u = await user.findById('6217192aa61d5d11970989ae')
  res.send({
    success: true,
    data: u
  })
})

// model.findOne({...})  通过条件搜索一个数据
app.use('/findone', async (req, res) => {
  const u = await user.findOne({
    // key:value 搜索的条件
  })
  res.send({
    success: true,
    data: u
  })
})

// model.find()   搜索当前集合下所有数据 返回一个数组
app.use('/findall', async (req, res) => {
  const u = await user.find()
  res.send({
    success: true,
    data: u
  })
})

// model.find({...}) 通过find中添加搜索条件 查找所有符合条件的数据
app.use('/findname', async (req, res) => {
  const u = await user.find({
    // key:value 搜索的条件
  })
  res.send({
    success: true,
    data: u
  })
})

// 查
// 数据过滤
// 设置过滤属性 让查找出来的数据只显示需要的部分属性
app.use('/findfilter', async (req, res) => {
  const u = await user.find({}, ['属性a', '属性b'])
  res.send({
    success: true,
    data: u
  })
})

// 设置过滤属性的另一种写法  属性:1为只显示该属性  属性:0为除这个属性不显示外显示其他属性
// 属性:1 与 属性:0不能一起使用 只能{ '属性a': 1, '属性b': 1} 或{ '属性a': 0, '属性b': 0}
app.use('/findfilters', async (req, res) => {
  const u = await user.find({}, {
    '属性a': 1,
    '属性b': 1
  })
  res.send({
    success: true,
    data: u
  })
})
// 查
// model.exists({...})

app.use('/login',(req, res)=>{
	const { userName, pwd } = req.body
	// 判断数据库中是否有 返回布尔值
	const u = await user.exists({ userName })
})
// 查
// 设置修饰符用于过滤数据

app.use('/findf',(req, res)=>{
	// 查找uid中为数组中的任意一个的数据
	const u = await user.find({ uid: {$in:[1,5,6,7]} })
})
// $gt $gte $lt $lte $or等 
// 查
// 设置修饰符用于过滤数据

app.use('/findf',(req, res)=>{
	// 查找uid中为数组中的任意一个的数据
	const u = await user.find({},{},{
		limit:5, // 截取的数据个数
		skip:5	// 偏移量 跳过的数据个数
	})
})



Md5加密

// 需要先引入模块
const utility = require('utility')		 	// 工具包 用于md5加密
const bodyParser = require('body-parser')	// 用于解析请求体 express默认自带 引入即可

app.use(bodyParser.json());					// 通过中间件挂载 解析表格和json
app.use(bodyParser.urlencoded({
  extended: false
}));
app.use('/md5', async (req, res) => {
  try {								// 在数据库中添加数据可能会出错 使用try catch在出错时进行捕捉
    const {
      userName,
      phone,
      addres,
      Uid,
      pwd,
      sex
    } = req.body 					// 从请求体中解构出来 需要的数据
    const u = await user.create({	
      // userName: 'zs',			// 数据格式
      // phone: '12345671231',
      // addres: '这是一个地址',
      // Uid: '440909888909880098',
      // pwd: '123123',
      // sex: 0,
      // status: 1

      userName,
      phone,
      addres,
      Uid,
      pwd,
      sex,
      pwd: '',					// 设置密码为空 在注册完成后再将二次加密的密码更新到pwd中
      status: 1
    })
    await user.findByIdAndUpdate(u.id, {			
    // createdAt为创建的时候的日期字符串 通过getTime()获得时间戳
      pwd: utility.md5(pwd + u.createdAt.getTime())	// 将用户的密码拼接上时间戳拼接起来再加密
    })												// 将加密后的密码更新到数据中
    res.send({
      success: true,
      data: u
    })
  } catch (error) {									// 出现错误时进行捕捉
    res.send({
      success: false
    })
    console.log('添加用户失败',error)
  }
})



乐观锁

在多请求同时修改数据库中的数据时,会影响数据最终的修改结果

在请求时获取到数据库中的数据 在修改时要先比较查询的数据是否被更改 再进行修改

如果在请求获得数据和修改的间隔中数据被修改 就修改失败


悲观锁

在多请求也同时修改数据库中的数据时,先将数据库锁住,不让其他用户进行修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Raccom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值