1.数据库概述及环境搭建
1.1 数据库作用
- 动态网站中的数据都是存储在数据库中的
- 数据库可以用来持久存储客户端通过表单收集的用户信息
- 数据库软件本身可以对数据进行高效的管理
http://www.czxy.com/article?id=1
http://www.czxy.com/article?id=2
1.2 什么是数据库
数据库即存储数据的仓库,可以将数据进行有序的分门别类的存储。它是独立于语言之外的软件,可以通过API去操作它
常见的数据库软件有:mysql、mongoDB、oracle
1.3 MongoDB下载安装
下载地址:https://www.mongodb.com/download-center/community
1.4 MongoDB Compass
MongoDB可视化操作软件,是使用图形界面操作数据库的一种方式
下载地址:https://www.mongodb.com/try/download/compass
1.5 数据库相关概念
在一个数据库软件中可以包含多个数据仓库,在每个数据仓库中可以包含多个数据集合,每个数据集合中可以包含多条文档(具体的数据)
术语 | 解释说明 |
---|---|
database | 数据库,mongoDB数据库软件中可以建立多个数据库 |
collection | 集合,一组数据的集合,可以理解为JavaScript中的数组 |
document | 文档,一条具体的数据,可以理解为JavaScript中的对象 |
field | 字段,文档中的属性名称,可以理解为JavaScript中的对象属性 |
1.6 Mongoose第三方包
使用Node.js操作MongoDB数据库需要依赖Node.js第三方包mongoose
使用npm install mongoose命令下载
1.7 启动MongoDB
在命令行工具中运行net start mongoDB即可启动MongoDB,否则MongoDB将无法连接
另外一种,创建mongo.conf文件写入数据库相关信息,在mongo.conf路径下,运行./mongod -f mongo.conf 或者
mongod.exe --config=mongo.conf
之后,打开MongoDB compass图形界面操作
1.8 数据库连接
使用mongoose提供的connect方法即可连接数据库
const mongoose = require('mongoose');
//mongoose.connect('mongodb://localhost/playground')// 使用mongodb协议 27017是数据库的默认端口,可不写
mongoose.connect('mongodb://localhost/db_demo', { useNewUrlParser: true ,useUnifiedTopology: true})
.then(() => console.log('success'))
.catch(() => console.log('erroe'));
1.9 创建数据库
在MongoDB中不需要显式创建数据库,如果正在使用的数据库不存在,MongoDB会自动创建
2.增删改查操作
2.1 创建集合mongoose.Schema&model()
创建集合分为两步,一是对对集合设定规则,二是创建集合,创建mongoose.Schema构造函数的实例即可创建集合
// 1.定义集合规则
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean
});
// 2.定义集合并应用规则
const Course = mongoose.model('Course', courseSchema); // courses
2.2 创建文档create()
创建文档实际上就是向集合中插入数据
分为两步:
1、创建集合实例
2、调用实例对象下的save方法将数据保存到数据库中
// 1.创建集合实例
const course = new Course({
name: 'database',
author: 'cc',
isPublished: false
});
// 2.将文档插入到数据库中
course.save();
创建文档的第2种方法: 通过构造函数的create方法
Course.create({name: 'database', author: 'ccc', isPublished: false}, (err, doc) => {
// 错误对象
console.log(err);
// 当前插入的文档
console.log(doc);
});
// Course.create()可以返回promise对象
Course.create({name: 'database', author: 'ccc', isPublished: false})
.then(doc => console.log(doc))
.catch(err => console.log(err));
2.3 数据库导入数据
找到mongodb数据库的安装目录,将安装目录下的bin目录放置在环境变量中,接着到json目录下输入,mongoimport –d 数据库名称 –c 集合名称 –-file 要导入的数据文件
mongoimport -d Course_demo -c users --file ./user.json
此时报错,JSON decoder out of sync
解决方法:将 --jsonArray 标志添加到命令中
mongoimport -d Course_demo -c users --jsonArray --file ./user.json
此时没有数据库Course_demo或者集合users,自动创建,向其追加json数据
2.4 查询文档
2.4.1 find()
// 根据条件查找文档 返回数组(参数为空则查找所有文档)
Course.find({_id: '5f3620c55bdba23230ef58fc'}).then(res=>console.log(res));
// 返回文档集合
[
{
_id: 5f3620c55bdba23230ef58fc,
name: 'database',
author: 'ccc',
isPublished: false,
__v: 0
}
]
2.4.2 findOne()
// 2. 根据条件查找文档 返回一个对象(匹配的第一条文档)
Course.findOne({_id: '5f361e2a23a10222804d76ad'}).then(res=>console.log(res));
// 返回文档
{
_id: 5f361e2a23a10222804d76ad,
name: 'database',
author: 'ccc',
isPublished: false,
__v: 0
}
2.4.3 常用查询操作
// 匹配大于 小于
User.find({age: {$gt: 20, $lt: 50}}).then(result => console.log(result))
// 匹配包含
User.find({hobbies: {$in: ['吃饭']}}).then(result => console.log(result))
// 选择要查询的字段 id默认得到,不需要时"-"
User.find().select('name email -_id').then(result => console.log(result))
// 将数据按照年龄进行排序
User.find().sort('age').then(result => console.log(result))
// skip 跳过多少条数据 limit 限制查询数量
User.find().skip(2).limit(2).then(result => console.log(result))
const mongoose = require('mongoose');
//1. 连接数据库
mongoose.connect('mongodb://localhost/Course_demo', { useNewUrlParser: true ,useUnifiedTopology: true});
//2. 定义集合规则
const userSchema = new mongoose.Schema({
"name": String,
"age": Number,
"password": String,
"email": String,
"hobbies": [String]
});
//3. 创建集合
const User = mongoose.model('User', userSchema);
User.find({
//4. 条件筛选
age: {$gt: 18, $lt: 40}
hobbies: {$in: ['吃','睡觉']}//字段包含的文本
}).select('name age hobby -_id')//结果包含和不包含的字段
.sort('age')
.skip(2)//跳过前两条文档
.limit(10)
.then(res => console.log(res));
//输出结果
[
{ name: '张三3', age: 20 },
{ name: '张三4', age: 20 },
{ name: '张三5', age: 20 },
{ name: '张三6', age: 20 },
{ name: '张三7', age: 20 },
{ name: '张三8', age: 20 },
{ name: '张三9', age: 20 },
{ name: '张三9', age: 20 },
{ name: '张三9', age: 20 },
{ name: '张三9', age: 20 }
]
2.5 删除文档
// 删除单个
Course.findOneAndDelete({}).then(result => console.log(result))
// 删除多个(不传参删除全部)
User.deleteMany({}).then(result => console.log(result))
User.findOneAndDelete({
name: '张三5'
}).then(res => console.log());
//输出结果为删除的文档
User.deleteMany({}).then(res => console.log(res));
//输出结果
{ n: 10, ok: 1, deletedCount: 10 }//ok为删除成功 n为删除个数
2.6 更新文档
// 更新单个
User.updateOne({查询条件}, {要修改的值}).then(result => console.log(result))//更新匹配的第一个
// 更新多个
User.updateMany({查询条件}, {要更改的值}).then(result => console.log(result))
User.updateOne({name: "张三1"}, {name: "李四"})
.then(res => console.log(res));
//输出结果
{ n: 1, nModified: 1, ok: 1 }//更新成功 更新1条
User.updateMany({}, {age: 56})
.then(res => console.log(res));
{ n: 10, nModified: 10, ok: 1 }//更新成功 更新10条
2.6 mongoose验证
在创建集合规则时,可以设置当前字段的验证规则,验证失败就则输入插入失败
- required: true 必传字段
- minlength:3 字符串最小长度
- maxlength: 20 字符串最大长度
- min: 2 数值最小为2
- max: 100 数值最大为100
- enum: ['html', 'css', 'javascript', 'node.js'] 数值必须为数组中的元素
- trim: true 去除字符串两边的空格
- validate: 自定义验证器
- default: 默认值
获取错误信息:error.errors['字段名称'].message
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true //必需字段
}
});
const Post = mongoose.model('Post', postSchema);
Post.create({}).then(res => console.log(res));
//报错:ValidationError验证错误
验证规则的使用:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/Course_demo', { useNewUrlParser: true ,useUnifiedTopology: true})
const postSchema = new mongoose.Schema({
title: {
type: String,
required: [true, '请传入文章标题'],//1. 自定义错误信息
minlength: 2,
maxlength: [5, '文章长度最大不超过5'],
trim: true
},
age: {
type: Number,
min: 18,
max: 100
},
date: {
type: Date,
default: Date.now //2.不传时 默认添加当前时间
},
category: {
type: String,
enum: {
values: ['html', 'css', 'js'],
message: '分类名称要在一定范围内'
} //3.传入规定 及错误信息
},
author: {
type: String,
// 4.自定义验证器
validate: {
validator: v => {
// 返回布尔值 验证v是否符合验证规则
return v && v.length > 4
},
message: '传入不符合规则'
}
}
});
const Post = mongoose.model('Post', postSchema);
Post.create({title: ' aaaaaa ', age: 56, category: 'c++', author: 'cc'})
.then(res => console.log(res))
.catch(err => {
// 5.获取错误信息对象
const errs = err.errors;
// 获取错误信息字段中的错误描述信息
for(var attr in errs) {
console.log(errs[attr].message);
}
});
//输出:
// 文章长度最大不超过5
// 分类名称要在一定范围内
// 传入不符合规则
2.7 集合关联
通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联
- 使用id对集合进行关联
- 使用populate方法进行关联集合查询
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/Course_demo', { useNewUrlParser: true ,useUnifiedTopology: true})
// 用户集合规则
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
}
});
// 文章集合规则
const postSchema = new mongoose.Schema({
title: {
type: String
},
author: {
type: mongoose.Schema.Types.ObjectId, //id的类型
ref: 'User' //关联的集合
}
});
const User = mongoose.model('User', userSchema);
const Post = mongoose.model('Post', postSchema);
User.create({name: '李思'})
.then(res => console.log(res));
// 1. 使用id对集合进行关联
Post.create({title: '123', author: '5f3655541d07b61a004753ad'})
.then(res => console.log(res));
// 2. 使用populate方法对某个字段 进行关联集合查询
Post.find().populate('author').then(res => console.log(res));
//输出
[
{
_id: 5f3655f7ed385f28d4fc99a7,
title: '123',
author: { _id: 5f3655541d07b61a004753ad, name: '李思', __v: 0 },
__v: 0
}
]
网友评论