Node.js入门指南(五)
目录
MongoDB
介绍
下载与启动
命令行交互
Mongoose
代码模块化
图形化管理工具
hello,大家好!上一篇文章我们介绍了express框架,这一篇文字主要介绍MongoDB。来对数据进行存储以及操作。
MongoDB
介绍
各位小伙伴应该多多少少都有接触到数据库,比如MySQL、SqlServer或者Oracle等。同样的MongoDB也是一种数据库,相比于其他的数据库,它操作语法与 JavaScript 类似,容易上手,学习成本低。MongoDB 是一个基于分布式文件存储的数据库,官方地址 。
Mongodb 中有三个重要概念需要掌握:
1️⃣数据库(database) 数据库是一个数据仓库,数据库服务下可以创建很多数据库,数据库中可以存放很多集合。
2️⃣集合(collection) 集合类似于 JS 中的数组,在集合中可以存放很多文档。
3️⃣文档(document) 文档是数据库中的最小单位,类似于 JS 中的对象。
{
"accounts": [
{
"id": "3-YLju5f3",
"title": "买电脑",
"time": "2023-02-08",
"type": "-1",
"account": "5500",
"remarks": "为了上网课"
},
{
"id": "mRQiD4s3K",
"title": "发工资",
"time": "2023-02-19",
"type": "1",
"account": "4396",
"remarks": "终于发工资啦!~~"
}
],
"users":[
{
"id": 1,
"name": "zhangsan",
"age":18
}
]
}
大家可以通过 JSON 文件来理解 Mongodb 中的概念 一个JSON 文件 好比是一个数据库 ,一个 Mongodb 服务下可以有 N 个数据库, JSON 文件中的 一级属性的数组值好比是集合, 数组中的对象好比是文档,对象中的属性有时也称之为字段。
下载与启动
那我们一起来安装MongoDB吧!建议选择 zip 类型, 通用性更强。配置步骤如下:
1️⃣将压缩包移动到 C:\Program Files 下,然后解压。
2️⃣创建 C:\data\db 目录,mongodb 会将数据默认保存在这个文件夹。
3️⃣将 bin 目录配置到环境变量 Path 中,为了方便后续方便使用 mongod 命令。
4️⃣以 mongodb 中 bin 目录作为工作目录,启动命令行,运行命令 mongod。
若看到的 waiting for connections 则表明服务 已经启动成功。
5️⃣再以 mongodb 中 bin 目录作为工作目录,启动命令行,使用 mongo 命令连接本机的 mongodb 服务。
注意:千万不要选中服务端窗口的内容 ,选中会停止服务,可以敲回车取消选中。
命令行交互
再来介绍一下,MongoDB中的一些命令行交互,包括数据库命令,集合的相关命令以及文档的相关命令。不过在后续用的不多,因此简单体验一下即可。
数据库命令 | 功能 |
show dbs
|
显示所有的数据库
|
use
数据库名
|
切换到指定的数据库,如果数据库不存在会自动创建数据库
|
db
|
显示当前所在的数据库
|
use
库名
db.dropDatabase()
|
删除当前数据库
|
集合命令 | 功能 |
db
.
createCollection
(
'集合名称'
)
|
创建集合
|
show collections
|
显示当前数据库中的所有集合
|
db.
集合名
.drop()
|
删除某个集合
|
db.
集合名
.renameCollection('newName')
|
重命名集合
|
文档命令 | 功能 |
db
.
集合名
.
insert
(
文档对象
);
|
插入文档
|
db.
集合名
.find(
查询条件
)
|
查询文档
|
db
.
集合名
.
update
(
查询条件
,
新的文档
)
db
.
集合名
.
update
({
name
:
'
张三
'
},{
$set
:{
age
:
19
}})
|
更新文档
|
db.
集合名
.remove(
查询条件
)
|
删除文档
|
在插入文档对象之后, mongodb会为该对象自动生成的唯一编号,用来唯一标识文档。
Mongoose
我们在前介绍命令行交互的时候都是在命令行窗口中进行与mongodb数据库进行交互,会比较麻烦,因此就引入了Mongoose,它是一个对象文档模型库,官网 http://www.mongoosejs.net/,方便使用代码操作 mongodb 数据库。接下来我们来使用mongoose来进行连接数据库以及进行相应的操作。
首先我们需要先对一个文件夹进行npm init初始化,因此mongoose也是一个包。然后使用npm i mongoose来进行下载Mongoose。然后导入mongoose,并连接mongodb服务,包括域名端口号,端口号默认是27017可写可不写,然后加上数据库的名称。(若数据库不存在,它会自动创建对应的数据库)。然后设置回调来提示连接的状态。
//导入mongoose
const mongoose=require('mongoose');
//连接mongodb服务
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');
//设置连接成功的回调
mongoose.connection.once('open',()=>{
console.log('连接成功');
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{
console.log('连接关闭');
});
//关闭mongodb连接
setTimeout(()=>{
mongoose.disconnect();
},2000)
数据库连接成功之后,我们使用mongoose向数据库插入文档。首先需要规定文档的结果对象,对象的属性名以及它对应的数值类型,截止创建文档模型对象,最后插入文档。使用.then()以及.catch接受成功以及失败的结果。最后可以use bilibili -> show collections -> db.books.find()。看数据库是否添加成功。插入的文档(对象)会默认添加两个属性,一个为_id,用于唯一表示,一个为_v,表示版本号。
//导入mongoose
const mongoose=require('mongoose');
//连接mongodb服务
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');
//设置连接成功的回调
mongoose.connection.once('open',()=>{
console.log('连接成功');
//创建文档结构对象
let BookSchema=new mongoose.Schema({
title:String,
author:String,
price:Number
});
//创建文档模型对象
let BookModel=mongoose.model('book',BookSchema);
//插入文档
BookModel.create({
title:'西游记',
author:'吴承恩',
price:19.9
}).then(data=>{
console.log(data);
mongoose.disconnect();
}).catch(err=>{
console.log(err);
})
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{
console.log('连接关闭');
});
接下来介绍一下mongoose的字段类型,上面的例子我们已经使用了String以及Number两种数据类型了。除了上面的两种还有以下的几种数据类型:
类型
|
描述
|
String
| 字符串 |
Number | 数字 |
Boolean | 布尔值 |
Array | 数组,也可以使用 [] 来标识 |
Date | 日期 |
Buffer | Buffer 对象 |
Mixed | 任意类型,需要使用 mongoose.Schema.Types.Mixed 指定 |
ObjectId | 对象 ID,需要使用 mongoose.Schema.Types.ObjectId 指定 |
Decimal128 | 高精度数字,需要使用 mongoose.Schema.Types.Decimal128 指定 |
Buffer类型主要是接收一些文件的,比如图片视频等。但是一般这些都放在静态资源文件中,比较少地存放在数据库中。一般数据库存放的是对应的文件地址,再通过地址找到对应的文件。这样效率会提高。其他的类型可以自行操作,都比较容易理解。
在我们插入文档数据时,我们还可以设置相应的约束,即字段值验证,Mongoose 有一些内建验证器,可以对字段值进行验证。
required:必填项。该属性如设置为true,是意味这对应的值不能为空。default: 默认值,但某个元素添加的时候没有设置对应的值,那么它就会使用默认的字,若添加时有值,它会使用添加的值。enum: [ ] ,表示枚举值,设置的值必须是数组中的某一个值,不然会报错。unique:表示唯一值,某个属性的值只能添加一次,后面再添加会重复,添加失败。不过在使用该属性时要确保自己的集合是新创建的才有效果。
接下来使用mongoose来实现文档的删除,删除可以是删除一条数据,也可以是实现批量地删除数据。首先我们先向数据库批量地插入数据,然后再有数据来给我们进行删除操作,插入部分演示如何实现批量地插入。上面代码只实现了单条数据的插入。
//1. 安装 mongoose
//2. 导入 mongoose
const mongoose = require('mongoose');
//设置 strictQuery 为 true
mongoose.set('strictQuery', true);
//3. 连接 mongodb 服务 数据库的名称
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');
//4. 设置回调
// 设置连接成功的回调 once 一次 事件回调函数只执行一次
mongoose.connection.once('open', () => {
//5. 创建文档的结构对象
//设置集合中文档的属性以及属性值的类型
let BookSchema = new mongoose.Schema({
name: String,
author: String,
price: Number,
is_hot: Boolean
});
//6. 创建模型对象 对文档操作的封装对象
let BookModel = mongoose.model('novel', BookSchema);
//7. 新增
BookModel.insertMany([{
name: '西游记',
author: '吴承恩',
price: 19.9,
is_hot: true
}, {
name: '红楼梦',
author: '曹雪芹',
price: 29.9,
is_hot: true
}, {
name: '三国演义',
author: '罗贯中',
price: 25.9,
is_hot: true
}, {
name: '水浒传',
author: '施耐庵',
price: 20.9,
is_hot: true
}, {
name: '活着',
author: '余华',
price: 19.9,
is_hot: true
}, {
name: '狂飙',
author: '徐纪周',
price: 68,
is_hot: true
}, {
name: '大魏能臣',
author: '黑男爵',
price: 9.9,
is_hot: false
},
{
name: '知北游',
author: '洛水',
price: 59,
is_hot: false
},{
name: '道君',
author: '跃千愁',
price: 59,
is_hot: false
},{
name: '七煞碑',
author: '游泳的猫',
price: 29,
is_hot: false
},{
name: '独游',
author: '酒精过敏',
price: 15,
is_hot: false
},{
name: '大泼猴',
author: '甲鱼不是龟',
price: 26,
is_hot: false
},
{
name: '黑暗王者',
author: '古羲',
price: 39,
is_hot: false
},
{
name: '不二大道',
author: '文刀手予',
price: 89,
is_hot: false
},
{
name: '大泼猴',
author: '甲鱼不是龟',
price: 59,
is_hot: false
},
{
name: '长安的荔枝',
author: '马伯庸',
price: 45,
is_hot: true
},
{
name: '命运',
author: '蔡崇达',
price: 59.8,
is_hot: true
},
{
name: '如雪如山',
author: '张天翼',
price: 58,
is_hot: true
},
{
name: '三体',
author: '刘慈欣',
price: 23,
is_hot: true
},
{
name: '秋园',
author: '杨本芬',
price: 38,
is_hot: true
},
{
name: '百年孤独',
author: '范晔',
price: 39.5,
is_hot: true
},
{
name: '在细雨中呼喊',
author: '余华',
price: 25,
is_hot: true
},]).then(data=>{
console.log(data);
mongoose.disconnect();
}).catch(err=>{
console.log(err);
});
});
// 设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
//1. 安装 mongoose
//2. 导入 mongoose
const mongoose = require('mongoose');
//设置 strictQuery 为 true
mongoose.set('strictQuery', true);
//3. 连接 mongodb 服务 数据库的名称
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');
//4. 设置回调
// 设置连接成功的回调 once 一次 事件回调函数只执行一次
mongoose.connection.once('open', () => {
//5. 创建文档的结构对象
//设置集合中文档的属性以及属性值的类型
let BookSchema = new mongoose.Schema({
name: String,
author: String,
price: Number,
is_hot: Boolean
});
//6. 创建模型对象 对文档操作的封装对象
let BookModel = mongoose.model('novel', BookSchema);
//7.删除一条数据
BookModel.deleteOne({_id:'6564996cdf9f7cab75d5e263'}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//批量删除
BookModel.deleteMany({is_hot:false}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
});
// 设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
介绍了新增以及删除,接下来介绍如何实现数据的更新以及查询操作。数据的更新同样包括单条数据的更新以及数据的批量更新。更新的方法需要接受一个查询的条件以及需要修改的内容。
//7.更新一条数据
BookModel.updateOne({name:'红楼梦'},{price:9.9}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//批量更新
BookModel.updateMany({author:'余华'},{is_hot:false}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
查询同样可以单条查询以及批量查询,还可以通过id来进行查询。当批量查询不传入参数时,会返回所有的数据。
//更新一条数据
BookModel.findOne({name:'狂飙'}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//根据 id 查询数据
BookModel.findById('6564996cdf9f7cab75d5e265').then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//批量查询带条件
BookModel.find({author:'余华'}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//批量查询不带条件
BookModel.find().then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
当我们的查询不是简单的查询而是需要更加复杂的条件时,我们就需要使用到运算符,逻辑运算以及正则来进行条件的控制。
条件 | 写法 |
> | $gt |
< | $lt |
>= | $gte |
<= | $lte |
!== | $ne |
或 | $or |
与 | $and |
正则 模糊查询 |
/要匹配的字符串/
|
//价格小于20的图书
BookModel.find({price:{$lt:20}}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//曹雪芹或者余华的书
BookModel.find({$or:[{author:'曹雪芹'},{author:'余华'}]}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//价格大于30 且小于70
BookModel.find({$and:[{price:{$gt:30}},{price:{$lt:70}}]}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//正则,搜素带有三的书名
BookModel.find({name:/三/}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
BookModel.find({name:new RegExp('三')}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
对于我们查询出来的数据并不都是我们真正想要的效果,因此我们可以对数据进行个性化读取。那下面以字段筛选、数据排序以及数据截取三种方式来进行介绍。
//设置字段 0:不要的字段 1:要的字段
BookModel.find().select({name:1,author:1,_id:0}).exec().then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//数据排序 1:升序 -1:倒序
BookModel.find().select({name:1,price:1,_id:0}).sort({price:1}).exec().then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
//数据截取 skip 跳过 limit 限定
BookModel.find().select({name:1,price:1,_id:0}).sort({price:1}).skip(3).limit(3).exec().then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
代码模块化
在实际的项目开发中,需要对代码进行模块化,让后期的维护更加地方便。思路就是将相同的可复用的代码单独地放置在一个文件中,并对其进行暴露,在需要用到的地方进行引入使用。将导入mongoose,连接mongodb服务,设置连接成功,失败以及关闭的回调,单独地放置在一个文件中。
module.exports = function (success, error) {
//导入配置文件
const {DBHOST,DBPOST,DBNAME}=require('../config/config');
//导入mongoose
const mongoose = require('mongoose');
//连接mongodb服务
mongoose.connect(`mongodb://${DBHOST}:${DBPOST}/${DBNAME}`);
mongoose.connection.once('open', () => {
success();
})
//设置连接错误的回调
mongoose.connection.on('error', () => {
error();
});
//设置连接关闭的回调
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
}
创建文档结构对象,创建文档模型对象也单独地放置在一个文件中。
const mongoose=require('mongoose');
//创建文档结构对象
let BookSchema = new mongoose.Schema({
title: String,
author: String,
price: Number
});
//创建文档模型对象
let BookModel = mongoose.model('book', BookSchema);
//暴露模型对象
module.exports=BookModel;
同时也可以将连接服务的地址单独地放置在一个文件中,后续只需要修改该文件即可修改相应的域名端口号以及数据库名。
module.exports={
DBHOST:'127.0.0.1',
DBPOST:27017,
DBNAME:'bilibili'
}
主文件进行导入即可。
//导入db文件
const db=require('./db/db');
//导入BookModel
const BookModel = require('./models/BookModel');
db(()=>{
//插入文档
BookModel.create({
title:'西游记',
author:'吴承恩',
price:92
}).then(data=>{
console.log(data);
// mongoose.disconnect();
}).catch(err=>{
console.log(err);
})
},()=>{
console.log('连接失败')
})
图形化管理工具
我们可以使用图形化的管理工具来对 Mongodb 进行交互,不需要再通过命令的方式来检查自己操作的数据是否生效,主要可以使用以下的两个工具,对应的下载地址如下:
Robo 3T 免费 https://github.com/Studio3T/robomongo/releases
Navicat 收费 https://www.navicat.com.cn/
好啦,本文就先到这啦!感谢阅读,持续更新~~