前言

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 file
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/mongodb-demo

相关网站:

Homebrew官网

MongoDB官网

monggose官网

Robo3T官网

macOS 包管理器 Homebrew 移除 MongoDB

--

欢迎转载,转载请注明出处:

https://champyin.com/2019/10/10/node.js操作数据库之MongoDB+mongoose篇/

本文同步发表于:

node.js操作数据库之MongoDB+mongoose篇 | 掘金

node.js操作数据库之MongoDB+mongoose篇的更多相关文章

  1. 使用navicat for mysql图形界面操作数据库、使用node.js操作数据库写接口

    1.先启动MYSQL服务 2.打开navicat for mysql, 点击链接,输入如下的内容: 3.新建数据表 4.数据库(新建一个db.js) //数据库链接配置 module.exports ...

  2. node.js操作数据库

    var sys = require('sys'); var Client = require('mysql').Client; var client = new Client(); client.us ...

  3. node.js零基础详细教程(7):node.js操作mongodb,及操作方法的封装

    第七章 建议学习时间4小时  课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...

  4. Node.js 操作Mongodb

    Node.js 操作Mongodb1.简介官网英文文档  https://docs.mongodb.com/manual/  这里几乎什么都有了MongoDB is open-source docum ...

  5. 使用node js 操作 Mysql 数据库

    使用node js 操作 Mysql 数据库 http://www.nodejs.org/ //node js 数据库操作 MySQL //使用https://github.com/felixge/n ...

  6. node.js操作MySQL数据库

    MySQL数据库作为最流行的开源数据库.基本上是每个web开发者必须要掌握的数据库程序之一了. 基本使用 node.js上,最受欢迎的mysql包就是mysql模块. npm install mysq ...

  7. Node.js、express、mongodb 实现分页查询、条件搜索

    前言 在上一篇Node.js.express.mongodb 入门(基于easyui datagrid增删改查) 的基础上实现了分页查询.带条件搜索. 实现效果 1.列表第一页. 2.列表第二页 3. ...

  8. [Node.js与数据库]node-mysql 模块介绍

    [Node.js与数据库]node-mysql 模块介绍   转载至:https://itbilu.com/nodejs/npm/NyPG8LhlW.html#multiple-statement-q ...

  9. [Node.js]操作mysql

    摘要 上篇文章介绍了node.js操作redis的简单实例,这里介绍如何操作mysql. 安装 安装mysql模块 cnpm install mysql 一个例子 新建一个mysql.js的文件,代码 ...

随机推荐

  1. 文档打印 js print调用打印dom内容

    1.首先按目前研究 print可以打印dom 2.被设置overflow:hidden 的模块,打印时会被截掉. 3.被设置成 display:none 的dom 打印不会有样式 边框等. 4.如果需 ...

  2. 第一章(Kotlin:定义和目的)

    实战Kotlin勘误 Kotlin 资源大全 Kotlin主要特征 目标平台 编写服务器端代码(典型的代表是Web应用后端) 创建Android设备上运行的移动应用(Android开发) 其他:可以让 ...

  3. [1]尝试用Unity3d制作一个王者荣耀(持续更新)->AssetBundle管理器

    如果已经看过本章节:目录传送门:这是目录鸭~ 1.AssetBundleManager: 首先我们创建一个文件夹,叫AssetBundleManager,再创建Csharp(即C#)脚本,名为Asse ...

  4. webpack中clean-webpack-plugin插件使用遇到的问题及解决方法

    webpack 会生成文件,然后将这些文件放置在 /dist 文件夹中,但是 webpack 无法追踪到哪些文件是实际在项目中用到的. 通常,在每次构建前清理 /dist 文件夹,是比较推荐的做法,因 ...

  5. 一些数组排序算法的简单实现(冒泡、插入、希尔、归并和qsort)

    #include <stdlib.h> #include <string.h> #include "sort.h" //冒泡排序 int bubbleSor ...

  6. SqlServer还原数据库时提示:异常终止,不能在此版本的SQL Server中启动,因为它包含分区函数

    场景 在SqlServer Management中进行数据库还原时提示: 数据库不能在此版本的SQL Server中启动,因为它包含分区函数. 点击左下角的查看详细信息 实现 电脑上安装的是SQL S ...

  7. STL中bitset的用法

    终于又来写博客了 == bitset存储的是二进数位,就和一个bool性数组差不多.用法上和数组的操作方式也差不多. 每位只占一个字节,大大优化了空间,可以通过数组形式访问. bitset定义 可以用 ...

  8. linux 操作系统级别监控 iostat 命令

    iostat命令可以查看当前机器磁盘io的数据 命令:iostat -x -k 1 -x:展示磁盘的扩展信息 -k:以k为单位展示磁盘数据 1:每1秒刷新一次 展示结果 util:磁盘IO使用率,单位 ...

  9. 06 (OC)* iOS中UI类之间的继承关系

    iOS中UI类之间的继承关系 此图可以更好的让你去理解iOS中一些底层的关系.你能够了解以及理解UI类之间的继承关系,你会更加明白苹果有关于底层的东西,更有助于你的项目开发由它们的底层关系,就能更加容 ...

  10. 微信支付JSAPI支付

    1.介绍 JSAPI支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付.应用场景有:    ◆ 用户在微信公众账号内进入商家公众号,打开某 ...