回调函数
MongoDB
- 关系型数据库与非关系型数据库
- 表就是关系
- 所有的关系型数据库都需要通过
sql
语言来操作 - 所有的关系型数据库在操作之前都需要设计表结构
- 而且数据表支持约束:唯一的、主键、默认值、非空
- 非关系型数据库非常灵活,有的非关系型数据库就是
key-value
对 - MongoDB是长的最像关系型数据库的非关系型数据库
- MongoDB不需要设计表结构,也就是是你可以任意往里面存数据,没有结构性这么一说
MongoDB数据库的基本概念
- 数据库(qq,taobao,baidu…)>集合(users,products…)>文档
- MongoDB可以有多个数据库,一个数据库可以有多个集合,一个集合可以有多个文档
{
qq: {
users: [
{ name: '张三', age: 15 },
{ name: '里斯', age: 15 },
{ name: '王五', age: 15 },
{ name: '张三123', age: 15 },
{ name: '张三微软', age: 15 },
...
],
products: [ ]
...
},
taobao: {
},
baidu: {
}
...
}
启动和关闭数据库
- 启动:
//mongodb默认使用mongod命令盘根目录下的data/db作为自己的数据存储目录
//第一次启动时,要先自己手动创建文件夹
mongod
- 如果想修改默认数据存储路径,可以
mongod --dbpath=数据存储目录路径
- 停止:
- 在开启服务的控制台,直接ctr+c,或者直接关闭服务台也可以
连接和退出数据库
- 连接
//该命令默认连接本机MongoDB服务
mongo
- 退出
//在连接状态输入exit回车,即可退出数据
exit
基本命令
- 查看显示所有数据库
show dbs
- 切换到指定的数据库(如果没有会新建)
use 数据库名称
- 查看当前操作数据库
db
- 插入数据
在Node中如何操作MongoDB数据
- 使用官方MongoDB包操作
- 使用第三方mongoose操作(基于MongoDB官方的
mongodb
包再一次封装)
npm init -y
npm i mongoose
官方指南
- 设计Schema发布Model
//1.导包
var mongoose = require('mongoose')
var Schema = mongoose.Schema
//2.连接本机MongoDB中的test数据库
mongoose.connect('mongodb://localhost/test')
//3.设计集合结构(表结构),字段名称就是表结构中的属性名称
var userSchema = new Schema({
username: {
type: String,
required: true//必须有
},
password: {
type: String,
required: true
},
email: {
type: String
}
})
//4.将文档结构发布为模型
//mongoose.model方法就是用来将一个架构发布为model
//第一个参数为传入一个名词单数字符串用来表示数据库名词
//mongoose会自动将大写的名词字符串生成小写复数的集合名词,如下集合名词为users
var User = mongoose.model('User', userSchema)
//5.有了模型构造函数 之后,就可以使用对users集合中的数据进行增删改查
- 增加数据
//写数据
var admin = new User({
username: 'admin',
password: '123456',
email: 'admin@admin.com'
})
//存储数据并判断是否存储成功
admin.save(function(err,ret){
if(err){
console.log('保存失败')
}else{
console.log(ret)
}
})
- 查询数据
//查询User集合内所有数据
User.find(function (err, ret) {
if (err) {
console.log('查询失败')
} else {
console.log(ret)
}
})
//按条件查询所有符合条件数据
User.find({
username: 'admin'
}, function (err, ret) {
if (err) {
console.log('查询失败')
} else {
console.log(ret)
}
})
//按条件查询符合条件的第一个数据(没有条件就查询集合内第一个数据)
User.findOne({
username: 'admin',
password: '123456'
}, function (err, ret) {
if (err) {
console.log('查询失败')
} else {
console.log(ret)
}
})
删除数据
User.remove({
username: '张三',
password: '123456'
}, function (err, ret) {
if (err) {
console.log('删除失败');
} else {
console.log(ret)
}
})
更新数据
//根据id来更新
User.findByIdAndUpdate('6097e51bf005f3076c7a72be', {
password: '123'
}, function (err, ret) {
if (err) {
console.log('更新失败')
} else {
console.log('更新成功')
}
})
使用Node操作MySQL数据库
- 安装
npm i mysql
Promise
- 回调地狱
- 异步操作读取文件,无法保证代码执行后,读出文件的顺序
var fs = require('fs')
fs.readFile('./data/a.txt', 'utf8',function (err, data) {
if (err) {
// console.log('读取失败')
//抛出异常
//1.阻止程序执行
//2.吧错误消息打印在控制台
throw err
}
console.log(data)
})
fs.readFile('./data/b.txt', 'utf8',function (err, data) {
if (err) {
// console.log('读取失败')
//抛出异常
//1.阻止程序执行
//2.吧错误消息打印在控制台
throw err
}
console.log(data)
})
fs.readFile('./data/c.txt', 'utf8',function (err, data) {
if (err) {
// console.log('读取失败')
//抛出异常
//1.阻止程序执行
//2.吧错误消息打印在控制台
throw err
}
console.log(data)
})
- 要想保证顺序,可以通过回调嵌套的方法
var fs = require('fs')
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
// console.log('读取失败')
//抛出异常
//1.阻止程序执行
//2.吧错误消息打印在控制台
throw err
}
console.log(data)
fs.readFile('./data/b.txt', 'utf8', function (err, data) {
if (err) {
// console.log('读取失败')
//抛出异常
//1.阻止程序执行
//2.吧错误消息打印在控制台
throw err
}
console.log(data)
fs.readFile('./data/c.txt', 'utf8', function (err, data) {
if (err) {
// console.log('读取失败')
//抛出异常
//1.阻止程序执行
//2.吧错误消息打印在控制台
throw err
}
console.log(data)
})
})
})
//这就是回调地狱
-
为了解决回调地狱的编码方式带来的问题,在EcmaScrpit6中新增了一个API:
Promise
-
promise基本语法
var fs = require('fs')
//Promise是一个构造函数
//创建Promise容器
//1.给别人一个承诺
//Promise容器一旦创建,就开始执行里面的代码
var p1 = new Promise(function (resolve, reject) {
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
//承诺容器中的任务失败了
// console.log(err)
//把容器的Pending状态变为Rejected
// 这里调用的reject就是调用了下面then方法的第二个函数
reject(err)
} else {
//承诺容器中的任务成功了
// console.log(data)
//把容器的Pending状态变为Resolved
//这里调用的resolve方法就是下面then方法传递的第一个function
resolve(data)
}
})
})
//p1就是那个承诺
//当p1成功了,然后(then)做指定操作
//then方法接收的function就是容器中的resolve函数
p1
.then(function (data) {
console.log(data);
}, function (err) {
console.log('读取文件失败了', err)
})
- 读取多个文件
var fs = require('fs')
var p1 = new Promise(function (resolve, reject) {
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
var p2 = new Promise(function (resolve, reject) {
fs.readFile('./data/b.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
var p3 = new Promise(function (resolve, reject) {
fs.readFile('./data/c.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
//当p1读取成功后
//当前函数中return 的结果就可以在后面then中的function接收
//当return一个promise对象的时候
//后续then方法中的参数为分别resolve方法,reject方法
p1
.then(function (data) {
console.log(data)
return p2
}, function (err) {
console.log('读取文件失败了', err)
})
.then(function (data) {
console.log(data)
return p3
})
.then(function (data) {
console.log(data)
})
- 代码封装
var fs = require('fs')
function pReadFile(filePath) {
return new Promise(function (resolve, reject) {
fs.readFile(filePath, 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
pReadFile('./data/a.txt')
.then(function (data) {
console.log(data)
//reutrn 调用pReadFile就会返回一个Promise对象
return pReadFile('./data/b.txt')
})
.then(function (data) {
console.log(data)
return pReadFile('./data/c.txt')
})
.then(function (data) {
console.log(data)
})