乐趣区

nodejs操作数据库之MongoDBmongoose篇

前言

node.js 的出现,使得用前端语法 (javascript) 开发后台服务成为可能,越来越多的前端因此因此接触后端,甚至转向全栈发展。后端开发少不了数据库的操作。MongoDB 是一个基于分布式文件存储的开源数据库系统。本文为大家详细介绍了如何用 node.js + mongoose 玩转 MongoDB。希望能帮到有需要的人。

由于我用 Mac 开发,以下所有操作都是在 Mac 下进行。

一、环境搭建

安装 Node.js

有 node 环境的可以跳过。

nodejs 官网提供了 macOS 安装包,直接下载安装即可。现在 nodejs 稳定版已经到了 12.11.1

安装 MongoDB

MongoDB 是为现代应用程序开发人员和云时代构建的基于文档的通用分布式数据库。

上个月(9 月)macOS 包管理器 Homebrew 宣布移除 MongoDB。原因是去年 10 月 MongoDB 宣布将其开源许可证从 GNU AGPLv3 切换到 SSPL(Server Side Public License),以此回应 AWS 等云厂商将 MongoDB 以服务的形式提供给用户而没有回馈社区的行为,MongoDB 希望从软件即服务上获取收入。Homebrew 认为 MongoDB 已经不再属于开源范畴 …

言归正传,由于上述原因,我们不能直接使用 brew install mongodb 来安装 MongoDB 了。好在 MongoDB 自己维护了一个定制化的 Homebrew tap。并在 Install MongoDB Community Edition 更新了安装步骤。

Mac 下 MongoDB 的最新安装步骤如下:

1. 首先安装 Homebrew

Homebrew 是 macOS 的包管理器。因为 OSX 默认不包含 Homebrew brew 包,所以要先安装,已经安装过的可以跳过。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

安装过程会有点长,终端输出信息超过一屏,这里我只截取了头尾两部分。

2. 然后获取下 MongoDB Homebrew Tap

brew tap mongodb/brew

3. 最后安装 MongoDB CE(社区版)

brew install mongodb-community@4.2

现在你的 Mac 上就已经安装好 MongoDB 环境了。

安装 mongoose

node.js 是可以直接操作 MongoDB 的,但是通过 MongoDB 命令语法直接编写 MongoDB 验证、数据类型转换和业务逻辑模版比较繁琐。所以我们使用了 mongoose。

mongoose 是 MongoDB 的一个对象模型工具,它对 MongoDB 的常用方法进行了封装,让 node.js 操作 MongoDB 更加优雅简洁。

刚才的 node.js 和 MongoDB 都是安装在全局环境,mongoose 则是安装在你的项目下:

cd your-project
npm i -S mongoose

现在,你的开发环境就已经全部安装好了。

二、启动 MongoDB 服务

要操作 MongoDB,首先要启动它。
有两种方式启动 MongoDB 服务:

1. 在前台运行

mongod --config /usr/local/etc/mongod.conf

前台运行的好处就是,可以查看一些反馈和日志,便于调试。另外如果要关闭服务,只需要在终端按 control + c 键即可。

2. 也可以作为 macOS 服务,在后台运行

brew services start mongodb-community@4.2

好处是开机就自动启动,随时可以使用。

这种启动方式,如果要关闭服务,可以通过 stop 命令:

brew services stop mongodb-community@4.2

现在,你的 MongoDB 数据库已经开启了。

三、操作 MongoDB

操作之前先解释一下 MongoDB 和 mongoose 里的一些核心概念。

MongoDB

  • MongoDB 中的数据记录是一种 BSON 格式的文件(BSON 是一种用二进制描述的 JSON 文件格式)。
  • MongoDB 将 文件 存储在 集合 中,将 集合 存储在 数据库 中。
  • MongoDB 的数据库、集合都不用手动创建。
  • 集合 collection: 相当于关系型数据库中的 表 table
  • 文件 document: MongoDB 的数据记录单位,相当于关系型数据库中的 记录 row

mongoose

  • schema: 在 mongoose 中,所有的东西都来源于一个 schema,每个 schema 映射了一个 MongoDB 的 集合 ,它定义了这个 集合 中的 文档 的骨架。
  • model: 一个 文件 的构造器,通过编译 schema 得到,一个 model 的实例就是一个 文件 model 负责从 MongoDB 数据库中创建和读取 文档

更多 mongoose 概念可以在 mongoose guide 查阅。

数据库操作:

1. 使用 mongoose 连接 MongoDB

在项目中创建 connection.js 文件

// connection.js file
const mongoose = require('mongoose');
const conn = mongoose.createConnection(

  // 连接地址,MongoDB 的服务端口为 27017
  // dbtest 是我要使用的数据库名,当往其中写数据时,MongoDB 会自动创建一个名为 dbtest 的数据库,不用事先手动创建。'mongodb://127.0.0.1:27017/dbtest', 

  // 一些兼容配置,必须加,你不写运行的时候会提示你加。{
    useNewUrlParser: true,
    useUnifiedTopology: true
   }
)
conn.on('open', () => {console.log('打开 mongodb 连接');
})
conn.on('err', (err) => {console.log('err:' + err);
})

运行:

node conection.js

可以看到打印出“打开 mongodb 连接”,并且运行一直在等待。

这说明现在已经成功连接上 MongoDB 了,接下来可以开始操作数据库了。

为了方便扩展起见,先对 connection.js 改造一下,让它作为模块导出,这样就可以在其他地方导入复用了。

// connection.js file
const mongoose = require('mongoose');
const conn = mongoose.createConnection(
  'mongodb://127.0.0.1:27017/dbtest',
  {
    useNewUrlParser: true,
    useUnifiedTopology: true
   }
)
conn.on('open', () => {console.log('打开 mongodb 连接');
})
conn.on('err', (err) => {console.log('err:' + err);
})

module.exports = conn; //commonJs 语法,导出 conn 模块。

2. 添加操作

save | create
新建insert.js

// insert.js file
let mongoose = require('mongoose');

// 导入连接模块
let connection = require('./connection');

// 创建 schema
let StudentSchema = new mongoose.Schema({
   name: String,
   age: Number
})

// 通过 connection 和 schema 创建 model
let StudentModel = connection.model('Student', StudentSchema);


// 通过实例化 model 创建文档
let studentDoc = new StudentModel({
    name: 'zhangsan',
    age: 20
})

// 将文档插入到数据库,save 方法返回一个 Promise 对象。studentDoc.save().then((doc) => {console.log(doc)
})

运行:

node insert.js

为了更直观看到操作数据库的结果,推荐大家安装一个数据库可视化工具:Robo3T,下载 mac 版安装即可。

点击 Robo3T 左上角连接我们的数据库后,可以看到 MongoDB 自动帮我们生成了数据库和集合,并且已经插入了一条记录:

或者还可以直接通过 Model 的 create 方法直接插入数据,返回的也是一个 Promise:

StudentModel.create({
    name: 'lisi',
    age: 19
}).then((doc) => {console.log(doc)
})

3. 读取操作

find
为更加合理复用代码,我们先把 StudentSchema 和 StudentModel 抽离出来:

新建StudentSchema.js

// StudentSchema.js file
const mongoose = require('mongoose');

let StudentSchema = mongoose.Schema({
    name: String,
    age: Number
})

module.exports = StudentSchema;

新建StudentModel.js

// StudentModel.js 
const connection = require('./connection');
const StudentSchema = require('./StudentSchema');

let StudentModel = connection.model('Student', StudentSchema);

module.exports = StudentModel;

然后新建 query.js 文件

// query.js file
const StudentModel = require('./StudentModel');

// 富查询条件,对象格式,键值对,下面为查询 name 为 lisi 的记录
StudentModel.find({name: 'lisi'}).then(doc => {console.log(doc);
})

运行

node query.js

可以看到 namelisi的记录被打印了出来。

如果想查询整个集合:

// 不放查询条件即查询所有的记录
StudentModel.find({}).then(doc => {console.log(doc);
})

可以看到集合中的所有记录被打印了出来。

4. 更新操作

update|updateOne|updateMany

新建update.js

// update.js file
const StudentModel = require('./StudentModel');

// update 方法接收 2 个参数,第一个是查询条件,第二个是修改的值
// 下面把 name 为 lisi 的记录,将他的 age 修改为 80
StudentModel.update({name: 'lisi'}, {age: 80}).then(result => {console.log(result)
})

进入 Robo3T,可以看到数据被更改,切换到表格模式更加直观:

不过在终端,提示DeprecationWarning: collection.update is deprecated. Use updateOne, updateMany, or bulkWrite instead.

意思是建议我们使用 updateOneupdateMany或者bulkWrite

  • update 更新查询到的所有结果,方法已经不提倡使用,已被 updateMany 替代。
  • updateOne 如果查询到多条结果,只更新第一条记录。
  • upateMany 更新查询到的所有结果。
  • bulkWrite 提供可控执行顺序的批量写操作。

为了代码的健壮性,我们应该根据建议将 update 方法换成 updateMany 方法。

另外,终端的输出 {n: 1, nModified: 1, ok: 1} 的意思是:

  • “n: 1”:查询到 1 条记录。
  • “nModified: 1”:需要修改 1 条记录。(如果修改值和原始值相同,则需要修改的就是 0 条)
  • “ok: 1”:修改成功 1 条。

5. 删除操作

remove|removeOne|removeMany|bulkWrite

新建remote.js

// remove.js file
const StudentModel = require('./StudentModel');

// delete 方法接收 1 个参数,就是查询条件
// 下面把 name 为 lisi 的记录删除
StudentModel.remove({name:'lisi'}).then((result) => {console.log(result);
});

进入 Robo3T,可以看到集合里已经没有 name 为 lisi 的记录了:

在看终端的输出,跟 update 类似,也提示建议使用新的方法代替。

意思是建议我们使用 removeOneremoveMany或者bulkWrite

remove 删除查询到所有结果,方法已经不提倡使用,已被 removeMany 替代。
removeOne 如果查询到多条结果,只删除第一条记录。
removeMany 删除查询到所有结果。
bulkWrite 提供可控执行顺序的批量写操作。

另外,终端的输出 {n: 1, ok: 1, deletedCount: 1} 的意思跟 update 的类似,就不累述了。

现在我们已经成功地对 MongoDB 数据库进行了 CRUD(添加、读取、更新、删除)操作。欢呼~

更多高级操作,可以到 mongoose API 文档查阅。

四、总结

梳理一下,一共讲了这些内容:

  1. node.js+MongoDB+mongoose 在 Mac 下的环境搭建,注意使用最新的 MongoDB 的安装方式。
  2. 在 Mac 下如何启动和关闭 MongoDB 服务。
  3. 介绍了 MongoDBmongoose 的基本核心概念。
  4. 使用 mongoose 连接以及增删改查 MongoDB 操作。可以使用 Robo3T 来更直观地观察数据库。

前端也能玩转数据库开发。
欢迎交流~

文章源码地址:https://github.com/yc111/mong…

相关网站:
Homebrew 官网
MongoDB 官网
monggose 官网
Robo3T 官网
macOS 包管理器 Homebrew 移除 MongoDB


欢迎转载,转载请注明出处:
https://champyin.com/2019/10/…

本文同步发表于:
node.js 操作数据库之 MongoDB+mongoose 篇 | 掘金

退出移动版