Node.js 连接 MongoDB

MongoDB是一种文档导向数据库管理系统,由C++撰写而成。

本章节我们将为大家介绍如何使用 Node.js 来连接 MongoDB,并对数据库进行操作。

如果你还没有 MongoDB 的基本知识,可以参考我们的教程: MongoDB 教程

安装驱动

本教程使用了 淘宝定制的 cnpm 命令 进行安装:

										$ cnpm install mongodb
									

接下来我们来实现增删改查功能。


创建数据库

要在 MongoDB 中创建一个数据库,首先我们需要创建一个 MongoClient 对象,然后配置好指定的 URL 和 端口号。

如果数据库不存在,MongoDB 将创建数据库并建立连接。

创建连接

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/yssmx " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; console . log ( " 数据库已创建! " ) ; db . close ( ) ; } ) ;

创建集合

我们可以使用 createCollection() 方法来创建集合:

创建集合

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = ' mongodb://localhost:27017/yssmx ' ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; console . log ( ' 数据库已创建 ' ) ; var dbase = db . db ( " yssmx " ) ; dbase . createCollection ( ' site ' , function ( err , res ) { if ( err ) throw err ; console . log ( " 创建集合! " ) ; db . close ( ) ; } ) ; } ) ;

数据库操作( CURD )

与 MySQL 不同的是 MongoDB 会自动创建数据库和集合,所以使用前我们不需要手动去创建。

插入数据

以下实例我们连接数据库 yssmx 的 site 表,并插入一条数据条数据,使用 insertOne()

插入一条数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; var myobj = { name : " 云搜索MX教程 " , url : " www.yssmx " } ; dbo . collection ( " site " ) . insertOne ( myobj , function ( err , res ) { if ( err ) throw err ; console . log ( " 文档插入成功 " ) ; db . close ( ) ; } ) ; } ) ;

执行以下命令输出就结果为:

												$ node test.js
文档插入成功
											

从输出结果来看,数据已插入成功。

我们也可以打开 MongoDB 的客户端查看数据,如:

										> show dbs
yssmx  0.000GB          # 自动创建了 yssmx 数据库
> show tables
site                     # 自动创建了 site 集合(数据表)
> db.site.find()
{ "_id" : ObjectId("5a794e36763eb821b24db854"), "name" : "云搜索MX教程", "url" : "www.yssmx" }
>
									

如果要插入多条数据可以使用 insertMany()

插入多条数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; var myobj = [ { name : ' 云搜索工具 ' , url : ' https://c.yssmx.com ' , type : ' cn ' } , { name : ' Google ' , url : ' https://www.google.com ' , type : ' en ' } , { name : ' Facebook ' , url : ' https://www.google.com ' , type : ' en ' } ] ; dbo . collection ( " site " ) . insertMany ( myobj , function ( err , res ) { if ( err ) throw err ; console . log ( " 插入的文档数量为: " + res . insertedCount ) ; db . close ( ) ; } ) ; } ) ;

res.insertedCount 为插入的条数。

查询数据

可以使用 find() 来查找数据, find() 可以返回匹配条件的所有数据。 如果未指定条件,find() 返回集合中的所有数据。

find()

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; dbo . collection ( " site " ) . find ( { } ) . toArray ( function ( err , result ) { // 返回集合中所有数据 if ( err ) throw err ; console . log ( result ) ; db . close ( ) ; } ) ; } ) ;

以下实例检索 name 为 "云搜索MX教程" 的实例:

查询指定条件的数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; var whereStr = { " name " : ' 云搜索MX教程 ' } ; // 查询条件 dbo . collection ( " site " ) . find ( whereStr ) . toArray ( function ( err , result ) { if ( err ) throw err ; console . log ( result ) ; db . close ( ) ; } ) ; } ) ;

执行以下命令输出就结果为:

													[ { _id: 5a794e36763eb821b24db854,
    name: '云搜索MX教程',
    url: 'www.yssmx' } ]
												

更新数据

我们也可以对数据库的数据进行修改,以下实例将 name 为 "云搜索MX教程" 的 url 改为 https://www.yssmx.com:

更新一条数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; var whereStr = { " name " : ' 云搜索MX教程 ' } ; // 查询条件 var updateStr = { $ set : { " url " : " https://www.yssmx.com " } } ; dbo . collection ( " site " ) . updateOne ( whereStr , updateStr , function ( err , res ) { if ( err ) throw err ; console . log ( " 文档更新成功 " ) ; db . close ( ) ; } ) ; } ) ;

执行成功后,进入 mongo 管理工具查看数据已修改:

													> db.site.find().pretty()
{
    "_id" : ObjectId("5a794e36763eb821b24db854"),
    "name" : "云搜索MX教程",
    "url" : "https://www.yssmx.com"     // 已修改为 https
}
												

如果要更新所有符合条的文档数据可以使用 updateMany()

更新多条数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; var whereStr = { " type " : ' en ' } ; // 查询条件 var updateStr = { $ set : { " url " : " https://www.yssmx.com " } } ; dbo . collection ( " site " ) . updateMany ( whereStr , updateStr , function ( err , res ) { if ( err ) throw err ; console . log ( res . result . nModified + " 条文档被更新 " ) ; db . close ( ) ; } ) ; } ) ;

result.nModified 为更新的条数。

删除数据

以下实例将 name 为 "云搜索MX教程" 的数据删除 :

删除一条数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; var whereStr = { " name " : ' 云搜索MX教程 ' } ; // 查询条件 dbo . collection ( " site " ) . deleteOne ( whereStr , function ( err , obj ) { if ( err ) throw err ; console . log ( " 文档删除成功 " ) ; db . close ( ) ; } ) ; } ) ;

执行成功后,进入 mongo 管理工具查看数据已删除:

													> db.site.find()
>
												

如果要删除多条语句可以使用 deleteMany() 方法

以下实例将 type 为 en 的所有数据删除 :

删除多条数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; var whereStr = { type : " en " } ; // 查询条件 dbo . collection ( " site " ) . deleteMany ( whereStr , function ( err , obj ) { if ( err ) throw err ; console . log ( obj . result . n + " 条文档被删除 " ) ; db . close ( ) ; } ) ; } ) ;

obj.result.n 删除的条数。

排序

排序 使用 sort() 方法,该方法接受一个参数,规定是升序(1)还是降序(-1)。

例如:

												{ type: 1 }  // 按 type 字段升序
{ type: -1 } // 按 type 字段降序
											

按 type 升序排列:

排序

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; var mysort = { type : 1 } ; dbo . collection ( " site " ) . find ( ) . sort ( mysort ) . toArray ( function ( err , result ) { if ( err ) throw err ; console . log ( result ) ; db . close ( ) ; } ) ; } ) ;

查询分页

如果要设置指定的返回条数可以使用 limit() 方法,该方法只接受一个参数,指定了返回的条数。

limit():读取两条数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; dbo . collection ( " site " ) . find ( ) . limit ( 2 ) . toArray ( function ( err , result ) { if ( err ) throw err ; console . log ( result ) ; db . close ( ) ; } ) ; } ) ;

如果要指定跳过的条数,可以使用 skip() 方法。

skip(): 跳过前面两条数据,读取两条数据

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; dbo . collection ( " site " ) . find ( ) . skip ( 2 ) . limit ( 2 ) . toArray ( function ( err , result ) { if ( err ) throw err ; console . log ( result ) ; db . close ( ) ; } ) ; } ) ;

连接操作

mongoDB 不是一个关系型数据库,但我们可以使用 $lookup 来实现左连接。

例如我们有两个集合数据分别为:

集合1:orders

												[
  { _id: 1, product_id: 154, status: 1 }
]
											

集合2:products

												[
  { _id: 154, name: '笔记本电脑' },
  { _id: 155, name: '耳机' },
  { _id: 156, name: '台式电脑' }
]
											

$lookup 实现左连接

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://127.0.0.1:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; dbo . collection ( ' orders ' ) . aggregate ( [ { $ lookup : { from : ' products ' , // 右集合 localField : ' product_id ' , // 左集合 join 字段 foreignField : ' _id ' , // 右集合 join 字段 as : ' orderdetails ' // 新生成字段(类型array) } } ] ) . toArray ( function ( err , res ) { if ( err ) throw err ; console . log ( JSON . stringify ( res ) ) ; db . close ( ) ; } ) ; } ) ;

删除集合

我们可以使用 drop() 方法来删除集合:

drop()

var MongoClient = require ( ' mongodb ' ) . MongoClient ; var url = " mongodb://localhost:27017/ " ; MongoClient . connect ( url , function ( err , db ) { if ( err ) throw err ; var dbo = db . db ( " yssmx " ) ; // 删除 test 集合 dbo . collection ( " test " ) . drop ( function ( err , delOK ) { // 执行成功 delOK 返回 true,否则返回 false if ( err ) throw err ; if ( delOK ) console . log ( " 集合已删除 " ) ; db . close ( ) ; } ) ; } ) ;

使用 Promise

Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。

如果你还不了解 Promise,可以参考 JavaScript Promise

以下实例使用 Promise 创建集合:

实例

const MongoClient = require ( " mongodb " ) . MongoClient ; const url = " mongodb://localhost/yssmx " ; MongoClient . connect ( url ) . then ( ( conn ) => { console . log ( " 数据库已连接 " ) ; var dbase = conn . db ( " yssmx " ) ; dbase . createCollection ( " site " ) . then ( ( res ) => { console . log ( " 已创建集合 " ) ; } ) . catch ( ( err ) => { console . log ( " 数据库操作错误 " ) ; } ) . finally ( ( ) => { conn . close ( ) ; } ) ; } ) . catch ( ( err ) => { console . log ( " 数据库连接失败 " ) ; } ) ;

Promise 数据操作

现在我们在一个程序中实现四个连续操作:增加 、查询 、更改 、删除。

实例

const MongoClient = require ( " mongodb " ) . MongoClient ; const url = " mongodb://localhost/ " ; MongoClient . connect ( url ) . then ( ( conn ) => { console . log ( " 数据库已连接 " ) ; const test = conn . db ( " testdb " ) . collection ( " test " ) ; // 增加 test . insertOne ( { " site " : " yssmx.com " } ) . then ( ( res ) => { // 查询 return test . find ( ) . toArray ( ) . then ( ( arr ) => { console . log ( arr ) ; } ) ; } ) . then ( ( ) => { // 更改 return test . updateMany ( { " site " : " yssmx.com " } , { $ set : { " site " : " example.com " } } ) ; } ) . then ( ( res ) => { // 查询 return test . find ( ) . toArray ( ) . then ( ( arr ) => { console . log ( arr ) ; } ) ; } ) . then ( ( ) => { // 删除 return test . deleteMany ( { " site " : " example.com " } ) ; } ) . then ( ( res ) => { // 查询 return test . find ( ) . toArray ( ) . then ( ( arr ) => { console . log ( arr ) ; } ) ; } ) . catch ( ( err ) => { console . log ( " 数据操作失败 " + err . message ) ; } ) . finally ( ( ) => { conn . close ( ) ; } ) ; } ) . catch ( ( err ) => { console . log ( " 数据库连接失败 " ) ; } ) ;

执行结果:

												数据库已连接
[ { _id: 5f1664966833e531d83d3ac6, site: 'yssmx.com' } ]
[ { _id: 5f1664966833e531d83d3ac6, site: 'example.com' } ]
[]
											

用异步函数实现相同的数据操作

实例

const MongoClient = require ( " mongodb " ) . MongoClient ; const url = " mongodb://localhost/ " ; async function dataOperate ( ) { var conn = null ; try { conn = await MongoClient . connect ( url ) ; console . log ( " 数据库已连接 " ) ; const test = conn . db ( " testdb " ) . collection ( " test " ) ; // 增加 await test . insertOne ( { " site " : " yssmx.com " } ) ; // 查询 var arr = await test . find ( ) . toArray ( ) ; console . log ( arr ) ; // 更改 await test . updateMany ( { " site " : " yssmx.com " } , { $ set : { " site " : " example.com " } } ) ; // 查询 arr = await test . find ( ) . toArray ( ) ; console . log ( arr ) ; // 删除 await test . deleteMany ( { " site " : " example.com " } ) ; // 查询 arr = await test . find ( ) . toArray ( ) ; console . log ( arr ) ; } catch ( err ) { console . log ( " 错误: " + err . message ) ; } finally { if ( conn != null ) conn . close ( ) ; } } dataOperate ( ) ;

运行结果:

												数据库已连接
[ { _id: 5f169006a2780f0cd4ea640b, site: 'yssmx.com' } ]
[ { _id: 5f169006a2780f0cd4ea640b, site: 'example.com' } ]
[]
											

运行结果完全一样。

很显然,异步函数是一种非常良好的编程风格,在多次使用异步操作的时候非常实用。

但是请勿在低于 7.6.0 版本的 node.js 上使用异步函数。