MongoDB数据库讲解
为什么要使用数据库?
在互联网上的网站主要有两大类,静态的还有动态的,关于静态的网站不必多说,所谓的动态网站就是可以根据对应的请求拿到不同的结果,什么意思呢,只可意会吧,你只需要知道动态网站是目前的标配就完事了
我们为什么要用MongoDB?mysql行不行?当然没有问题。但是!学习MongoDB的学习成本比较低,什么意思呢?我的意思是,由于MongoDB数据库开发的接口是js的语法,还有内部的存储格式是json所有你特别容易上手,
MongoDB是一个软件,去下载吧少年
这里需要两个软件,一个是本身的数据库软件,还有一个可视化的数据库软件
百度点击下载就完事!我认为我这里没有必要教你如何安装软件
需要说明的一件事,你需要知道这两个文件夹,方便后面的排错
如何查看你的MongoDB已经安装成功?其实这个软件会在你的电脑上开一个端口
localhost:27017,如果你访问没有报错,就说明你成功安装了这个软件
数据库基础知识
- 数据仓库,database
所谓的数据仓库,指的是一个数据库软件,可以提供给多个网站进行服务,每一个网站都有自己的对应的数据仓库,仓库里就是关于本网站的数据内容 - 集合,collection
集合是在仓库下,一组数据的集合,可以理解为js的数组 - 文档,document
集合下面有文档,文档是一条具体的数据,类似于js中的对象 - 字段,field
文档里面有数据对应的字段,什么是字段?就相当于js中的键值对中的键,当然你也可以理解为对象的属性
有点模糊?没关系。看下面的这个图,你就会感觉爽多了
使用数据库(一)
-
首先,我们打开我们的软件。你不需要做任何的修改,直接点击链接,就完事。
-
第二步,我们看看数据库里面有什么 注意这里的admin还有config还有local不要动!!!
点击创建就可以创建仓库了,我们先创建一个名字叫做api的仓库
-
再然后我们创建一个仓库,下面的的就是我的数据库了,里面的所有的东西,这里的创建还是非常简单的,由于提供了可视化软件,所以操作非常的容易
-
那么你可能郁闷了,哇这么多的字段还有数据,老李,你让我一个一个打吗?你在想屁吃吧,
没关系!就知道你们懒啊,我们可以下面的方式直接导入现有的数据,注意啊,这里你不能再使用之前的GUI软件了,我们换一个软件,接下里的开发都在这里面进行,MongoBooster,
使用说明:你直接百度一下吧,使用去起来非常的简单!拖拽json文件回去就可以完成一次数据库的导入
使用数据库(二)
你以为会用GUI就完事了??不不不不,你是程序员,大哥!你需要用代码!!!
- 在Node中下载一个依赖npm install mongoose,这样你才能通过Node操作数据库
- 在在电脑中启动MongoDB,用到两个命令。开启服务:net start mongoDB 关闭服务:net stop mongoDB
- 在node中链接到自己的数据库
语法:
// 注意我们的返回的是一个promise对象
// 引入mongoose第三方模块 用来操作数据库
const mongoose = require('mongoose');
// 数据库连接
//这个是返回一个promise对象,(异步,
//这个地方没有playground也是ok的,如果没有他会自己帮我创建这个数据库
// { useNewUrlParser: true }这个参数不用管你加上就完事
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true })
// 连接成功
.then(() => console.log('数据库连接成功'))
// 连接失败
.catch(err => console.log(err, '数据库连接失败'));
使用数据库(三,增)
导学:我们的库如果没有就会自动创建一个库,
有了库,我们就可创建库的下一个级别:集合
- 第一种创建方式
- 第一步:设置集合的规则
const mongoose = require('mongoose');
//对集合设定规则
// 设定集合规则
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean
});
// 创建集合并应用规则
- 第二步:创建集合,获得一个代表当前集合的集合构造函数,这个集合构造函数非常 重要
const Course = mongoose.model('Course', courseSchema); // Course就是集合的名字。注意这里你需要给一个大写,
//返回一个构造函数,然后我们拿东西去接过来就完事
- 第三步,往数据库里面丢一点东西
//5.注意你需要插进数据,要不然它不会创建出来
// 6.把集合实例创建出来,并且把数据传入,于是乎你就有了一个数据对象,也就是创建文档
let coures = new Course({
name: 'node教程',
author: '老李',
isPublished: true
})
// 7.调用集合对象下的方法 插入数据
coures.save()
- 我们还有一种方式
// 第一个是数据库。第二个回调函数
//Course是之前的的构造函数
Course.create({name: 'JavaScript基础', author: '老李', isPublish: true}, (err, doc) => {
// 错误对象
console.log(err)
// 当前插入的文档
console.log(doc)
});
//有回调函数的时候基本上都是异步的api,Course.create()返回promise对象
Course.create({name: 'Node基础', author: '老李', isPublish: true})
.then(doc => console.log(doc))
.catch(err => console.log(err))
- 导入现有的数据,通过代码
基础的语法是这样的-在命令行。这个是命令不是代码:
mongoimport –d 数据库名称 –c 集合名称 –file 要导入的数据文件
小心:一般来说,如果是为window系统添加一些命令 你需要像下面的样子一样去设置
找到mongodb数据库的安装目录,将安装目录下的bin目录放置在环境变量中。
mongoimport -d playground -c users -file .\user.json
使用数据库(四,删)
注意我们的所有的数据的操作的api都是在Coures集合构造函数下的,我的意思是:之前我们说的集合构造函数,非常的重要!
删除文档的语法:注意,他们都是返回promise对象,then之后都是拿到的被删除的文档,{}里卖是丢查询条件
// 删除单个
Course.findOneAndDelete({}).then(result => console.log(result))
// 删除多个 返回,一个对象ok:1表示操作成功。n:表示删除四个
User.deleteMany({}).then(result => console.log(result))
使用数据库(五,改)
注意我们的所有的数据的操作的api都是在Coures集合构造函数下的,我的意思是:之前我们说的集合构造函数,非常的重要!
其实啊改的操作,也就是更新操作
基础的语法:
// 更新单个
User.updateOne({查询条件}, {要修改的值}).then(result => console.log(result))
// 更新多个
User.updateMany({查询条件}, {要更改的值}).then(result => console.log(result))
实战演示:
// 找到要删除的文档并且删除
// 返回是否删除成功的对象
// 如果匹配了多条文档, 只会删除匹配成功的第一条文档
// User.updateOne({name: '李四'}, {age: 120, name: '李狗蛋'}).then(result => console.log(result))
// 找到要删除的文档并且删除
// 如果传递的是一个{} 表示修改所有的
User.updateMany({}, { age: 300 }).then(result => console.log(result))
使用数据库(六,查)
注意我们的所有的数据的操作的api都是在Coures集合构造函数下的,我的意思是:之前我们说的集合构造函数,非常的重要!
它在这里
const Course = mongoose.model('Course', courseSchema); // Course就是集合的名字。注意这里你需要给一个大写,
//返回一个构造函数,然后我们拿东西去接过来就完事
看看我们的怎么做查询操作
语法:
// 根据条件查找文档(条件为空则查找所有文档)
当前的集合构造函数.find().then(result => console.log(result))
注意它的返回值:数组,如果查询的数据不存在就会返回一个空数组
+++
// 引入mongoose第三方模块 用来操作数据库
const mongoose = require('mongoose');
// 数据库连接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true })
// 连接成功
.then(() => console.log('数据库连接成功'))
// 连接失败
.catch(err => console.log(err, '数据库连接失败'));
// 创建集合规则
const userSchema = new mongoose.Schema({
name: String,
age: Number,
email: String,
password: String,
hobbies: [String] //这个是一个数组,数组里面是字符串
});
// 使用规则创建集合
const User = mongoose.model('User', userSchema); //返回是一个集合的构造函数
// 查询文档
// 查询用户集合中的所有文档
// User.find().then(result => console.log(result)); //find方法。返回的总是一个文档的集合(数组,需要说明的是,.then是promise对象的方法,这个返回的是程序的结果
// 通过_id字段查找文档
// User.find({ _id: '5c09f267aeb04b22f8460968' }).then(result => console.log(result))
// findOne方法返回一条文档 默认返回当前集合中的第一条文档
// User.findOne({ name: '李四' }).then(result => console.log(result))
// 查询用户集合中年龄字段大于20并且小于40的文档
// User.find({ age: { $gt: 20, $lt: 40 } }).then(result => console.log(result)) //这里有一些转意字符,你需要了解$gt = >号,$lt = <号
// 查询用户集合中hobbies字段值包含足球的文档,可以用于实现网站的搜索功能
// User.find({hobbies: {$in: ['足球']}}).then(result => console.log(result)) //$in是包含的意思
// 选择要查询的字段
// User.find().select('name email -_id').then(result => console.log(result))
// 根据年龄字段进行升序排列,可以用来实现价格的查询等等操作
// User.find().sort('age').then(result => console.log(result))
// 根据年龄字段进行降序排列
// User.find().sort('-age').then(result => console.log(result))
// 查询文档跳过前两条结果 限制显示3条结果,这个可以实现分页功能
User.find().skip(2).limit(3).then(result => console.log(result))
User.find().skip(2).limit(3).then(result => console.log(result))
skip(2)跳过前两个文档
limit(3)只想要三个
+++
总结:
// 返回的都是文档
find()是返回这个东西
[{
_id: 5c0917ed37ec9b03c07cf95f,
name: 'node.js基础',
author: 'laoli'
},{
_id: 5c09dea28acfb814980ff827,
name: 'Javascript',
author: 'laoli'
}]
findOne()返回是这个东西
{
_id: 5c0917ed37ec9b03c07cf95f,
name: 'node.js基础',
author: 'laoli'
}
验证
上面意思呢?指的是设置设置字段的插入规则,验证一下看看你的字段符不符合我的规则,如果符合就允许用户插入字段
需求:比如这里我们创建文章集合
// 引入mongoose第三方模块 用来操作数据库
const mongoose = require('mongoose');
// 数据库连接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true })
// 连接成功
.then(() => console.log('数据库连接成功'))
// 连接失败
.catch(err => console.log(err, '数据库连接失败'));
//这里是做一些mongodb的验证,注意啊这里的规则可以是对象类型
const postSchema = new mongoose.Schema({
title: {
type: String,
// 必选字段
required: [true, '请传入文章标题'],
// 字符串的最小长度
minlength: [2, '文章长度不能小于2'],
// 字符串的最大长度
maxlength: [5, '文章长度最大不能超过5'],
// 去除字符串两边的空格
trim: true
},
age: {
type: Number,
// 数字的最小范围
min: 18,
// 数字的最大范围
max: 100
},
publishDate: {
type: Date,
// 默认值
default: Date.now //这个是会传出一个日期,这个是默认的传入的
},
category: {
type: String,
// 枚举 列举出当前字段可以拥有的值,这个是枚举,
// 所谓的枚举 就是一个一个举例验证出来
enum: {
values: ['html', 'css', 'javascript', 'node.js'],
message: '分类名称要在一定的范围内才可以'
}
},
author: {
type: String,
//我们程序员自定义的验证规则
validate: {
validator: v => { //v是形参,是当前用户插入的值
// 返回布尔值
// true 验证成功
// false 验证失败
// v 要验证的值
//短路运算
return v && v.length > 4
},
// 自定义错误信息
message: '传入的值不符合验证规则,最少是4个以上1'
}
}
});
const Post = mongoose.model('Post', postSchema);
//需求:如何一次性的把所有的不符合验证规则的错误信息都获取出来
Post.create({ title: 'aa', age: 60, category: 'java', author: 'bd' })
.then(result => console.log(result))
.catch(error => {
// 获取错误信息对象,这个获取过来的其实就是报错的信息
const err = error.errors;
// 循环错误信息对象
for (var attr in err) { //注意一下这个地方的for遍历循环的操作要点
// 将错误信息打印到控制台中
console.log(err[attr]['message']);
}
})
MongoDB高级——集合关联
这个是比较难的
需求:在一个数据中,包含其他的数据。
通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联。
使用id对集合进行关联
使用populate方法进行关联集合查询
语法规范:
// 用户集合
const User = mongoose.model('User', new mongoose.Schema({ name: { type: String } }));
// 文章集合
const Post = mongoose.model('Post', new mongoose.Schema({
title: { type: String },
// 使用ID将文章集合和作者集合进行关联,是一个id的类型mongoose.Schema.Types.ObjectId,固定死的,第二个参数就是关联谁
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
}));
//联合查询
Post.find()
.populate('author')
.then((err, result) => console.log(result));
示例代码:
// 引入mongoose第三方模块 用来操作数据库
const mongoose = require('mongoose');
// 数据库连接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true })
// 连接成功
.then(() => console.log('数据库连接成功'))
// 连接失败
.catch(err => console.log(err, '数据库连接失败'));
// 用户集合规则
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
}
});
// 文章集合规则
const postSchema = new mongoose.Schema({
title: {
type: String
},
author: {
type: mongoose.Schema.Types.ObjectId, //注意一下 mongodb的id是有一种特殊类型的,这个就是那个类型
ref: 'User' //ref就是关联的意思!指定关联另外一个集合
}
});
// 用户集合
const User = mongoose.model('User', userSchema);
// 文章集合
const Post = mongoose.model('Post', postSchema);
// 创建用户
User.create({ name: 'itheima' }).then(result => console.log(result));
// 创建文章
Post.create({ titile: '123', author: '5c0caae2c4e4081c28439791' }).then(result => console.log(result));
//查询作者
Post.find().populate('author').then(result => console.log(result))