版本说明

"MongoDB": "4.0.9",  // cmd命令窗输入:mongo --version
"node": 10.13.0,      // cmd命令窗输入:node -v
"npm": 6.10.3,        // cmd命令窗输入:npm -v
"express": 4.16.0     // cmd命令窗输入:express --version

以下主要是 Mongodb 在 node.js 中的使用,通过对象模型工具 mongoose 操作数据库,操作数据库通过可视化工具 Robo 3T

 


一、在 node.js 中连接数据库的方式,通过命令  node app.js 运行启动文件即可

1.1、启动文件内容大致如下,其中引入的模板(中间件),需要通过 npm 进行安装

一般通过 npm install xxxx --save:表示生产环境和开发环境都需要此包, npm install xxx --save-dev :表示开发环境需要此包

 

1.2、定义启动文件 app.js         

mongodb锁表fsync lock mongodb 临时表_mongoose

/**
 * 启动express服务
 */

//1. 引入express模块
const express = require('express');

//2. 引入body-parser才能拿到post的参数
const bodyParser = require('body-parser');

//3. 引入定义的接口路由
const user = require('./router/users');

// 4. 引入cors包
var cors = require('cors');

// 5 .创建app对象
const app = express();

// 解决post接口获取为正常的application/json
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// 解决跨域问题
app.use(cors({
  origin: ['http://localhost:8099'],  // 允许指定域名访问
  methods: ['GET', 'POST', 'PUT', 'DELETE'],                      // 允许指定请求方式
  alloweHeaders: ['Content-Type', 'Authorization'],               // 只允许带这两种请求头的链接访问
  credentials: true                                               // 允许跨域携带cookie值
}));

// 使用接口/路由
app.use('/user', user);
app.use('/', (req, res) => {
  res.send('Oh you are success!!')
});

// 定义服务启动端口
app.listen(3000, () => {
  console.log('app listening on port 3000')
})

 

 


二、获取数据表中的字段,通过封装数据模型 mongoose.Schema

2.1、定义封装数据表的文件 tableSchema.js                            

mongodb锁表fsync lock mongodb 临时表_mongoose_02

 


 

2.2、数据库中的 users 表如下


 

2.3、定义连接数据库,导出数据表等操作的文件  db.js

// 引入mongoose模块
const mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
// 引入数据表
const tableSchema = require('./tableSchema');

/**
 * 数据库地址(myUser 表示对应的数据库名)
 * Connecting to Mongod instance.
 */
const dbHost = 'mongodb://localhost/myUser';


/**
 * 连接mongodb数据库
 * @param {参数1} 'mongodb数据库启动的地址'
 * @param {参数2} 'parser过时,调用新的解析方法'
 * @param {参数3} '回调函数,用于判断是否连接成功'
 */
mongoose.connect(
    dbHost,
    {
        useNewUrlParser: true
    },
    err => {
        if (err) console.log("**********【数据库连接失败】**********" + err);
        else console.log("**********【数据库连接成功】**********");
    });


const db = mongoose.connection;
db.on('error', function () {
    console.error.bind(console, 'Database connection error HA');
})
db.once('open', function () {
    console.log('The Database has connected HA');
})

module.exports = tableSchema; // 导出数据表

 


三、在定义接口逻辑中,通过对象模型 操作数据表,如以下 user.js 接口文件

mongodb锁表fsync lock mongodb 临时表_Mongodb_03

 

【 以下是重点代码!!!

mongodb锁表fsync lock mongodb 临时表_Nodejs_04

mongodb锁表fsync lock mongodb 临时表_Nodejs_05

mongodb锁表fsync lock mongodb 临时表_Nodejs_06

 

 


四、结合上述,以下就只写 操作数据库的代码

4.1、mongoose 中的查找 find ( 数据模型以 Users 为例,其中包含的字段如上,第二点的2.1 )      

        

mongodb锁表fsync lock mongodb 临时表_Mongodb_07

Users.find({})
.then( user => { 
    console.log(user) 
})
.catch(err => {
     console.log(`${err.name} : ${err.message}`)
})

 

4.2、mongoose 中的模糊查询 find

const nameReg = new RegExp('王二狗', 'i');  // 搜索条件、'i'不区分大小写
let page = 1;
let size = 10;

/**
* '$or' 通过字段 name 进行模糊查询
* '{ token : 0 }' 表示不显示 token 字段
* 'sort({ id : 1 })'  通过 id 进行正序排序
* 'skip(  page * size ), limit( size )' 查询了第 10 条到第 20 条数据
*/
Users.find(
    {
        $or: [
            { name: {$regex: nameReg } }
        ]
    },
    {
        token: 0
    },
    sort({ id : 1 }),
    skip( page * size ),
    limit( size )
)
.then( user => { 
    console.log(user) 
})
.catch(err => {
     console.log(`${err.name} : ${err.message}`)
})

 

4.3、mongoose 中的创建 create (一条:传对象 Object; 多条:传数组 Array )

let obj = { username: '张胖子', age: 16 }

// 增加一条数据
Users.create(obj)
.then( user => { 
    console.log(user) 
})
.catch(err => {
     console.log(`${err.name} : ${err.message}`)
})
let arr = [
    { username: '张胖子', age: 16 },
    { username: '蔡妍', age: 18 },
    { username: '李沁', age: 20 }
]

// 增加多条数据
Users.create(arr)
.then( user => { 
    console.log(user) 
})
.catch(err => {
     console.log(`${err.name} : ${err.message}`)
})

 

4.4、mongoose 中的更新 findOneAndUpdate 

let newObj = { username: '蔡妍', age: 60 }

/**
* 条件是 username 等于 '蔡妍'
* ' $set ' 表示需要修改后的对象值,需要包含所有原本对象所需的字段,即根据 username 的值覆盖原对象
* ' {new: true} ' 表示返回修改后的对象值,不设置默认返回修改之前的数据
*/
Users.findOneAndUpdate(
    {
        username: newObj.username
    },
    {
        $set: newObj
    },
    {
        new: true
    }
)
.then( user => { 
    console.log(user) 
})
.catch(err => {
     console.log(`${err.name} : ${err.message}`)
})

 

4.5、mongoose 中的删除 : findOneAndRemove(删除一条)、 deleteMany(删除多条)

let deleteName = '蔡妍'

/**
* 删除 username 等于 '蔡妍' 的一条数据
*/
Users.findOneAndRemove(
    {
        username: deleteName
    }
)
.then( user => { 
    console.log(user) 
})
.catch(err => {
     console.log(`${err.name} : ${err.message}`)
})
let deleteName = '蔡妍'

/**
* 删除 username 等于 '蔡妍' 的所有数据 (多条数据)
*/
Users.deleteMany(
    {
        username: deleteName
    }
)
.then( user => { 
    console.log(user) 
})
.catch(err => {
     console.log(`${err.name} : ${err.message}`)
})

 


五、mongoose 中的其他操作(如 创建临时表、多表查询等)

5.1、mongoose 中的创建临时表 :通过聚合( aggregate )处理数据,参考官方文档

         

mongodb锁表fsync lock mongodb 临时表_Mongodb_08

【 如 权限表 permission ,表中的字段如下】

mongodb锁表fsync lock mongodb 临时表_Nodejs_09

mongodb锁表fsync lock mongodb 临时表_Mongodb_10

【 在对应的 node.js 项目中,引入权限表的相关数据等 】 

mongodb锁表fsync lock mongodb 临时表_mongodb锁表fsync lock_11

mongodb锁表fsync lock mongodb 临时表_Mongodb_12

mongodb锁表fsync lock mongodb 临时表_mongodb锁表fsync lock_13

 

【 用 aggregate 创建一个临时表,获取权限表 permission 中的 children 字段中数据 ,参考官方文档

/** * 【创建权限临时表】 * "$unwind" 如 将有字段是一个children数组( 包含三个元素 )的数据,返回以children为字段名,当前children字段的数据 对应 之前children数组下的元素,即一条数据替换成三条数据 * "$group" 需要以"_id"进行分组,定义"_id"对应的字段 ( 临时表拥有字段: _id、perm ) * "$push" 将"children"字段下的数据,作为元素添加到 "perm" 数组中 * "$sort" 以"_id"进行正序排序 ( "1"表示正序,"-1"表示倒序 ) * "$out" 输出临时表的名字 */ Permission.aggregate( [ { "$unwind": "$children" }, { $group: { _id: "$children.id", perm: { $push: "children" } } }, { $sort: { _id: 1 } }, { $out: "temp_perm" } ] ) .then( tempPerm => { // 创建成功后返回一个空数组 console.log(tempPerm) }) .catch(err => { console.log(`${err.name} : ${err.message}`) })

 

【 临时表在数据库显示如下,即 之前 children下的每个元素,组成了一条数据 】 

mongodb锁表fsync lock mongodb 临时表_mongodb锁表fsync lock_14

mongodb锁表fsync lock mongodb 临时表_mongoose_15

 

5.2、mongoose 中的多表查询,通过聚合( aggregate )处理数据,参考官方文档 ( 以下说明了两张表、三张表的操作 )

        

mongodb锁表fsync lock mongodb 临时表_Nodejs_16

两张表!!

  • 【 需求:
  • 思路: 用户表 users 和 用户角色表 users_roles, 其中的关联是,用户表 usres 中的字段 id ,与用户角色表 users_roles 的字段 user_id 一致( user_id 是外键,即类似对象中 users["id"] = users_roles["user_id"] = 3 ) 】 其中 "$lookup"参考这里
  • 【 两张表在数据库中的字段定义如下: 】

mongodb锁表fsync lock mongodb 临时表_Nodejs_17

mongodb锁表fsync lock mongodb 临时表_Nodejs_18

let id = 3; /** * 聚合(aggregate)主要用于处理数据,并返回计算后的数据结果,有点类似sql语句中的 count(*) * "$project" 只显示(1)或隐藏(0)对应属性 * "$match" 用于过滤数据,只输出符合条件的文档,此处是 只输出 id=3 的数据 * "$lookup" 根据主外键联表查询(外键是相对主表中的字段名,此处是 user_id) * "from" 表示 在同一数据库中指定要执行联接的集合。 * "localField" 表示 指定从文档输入到$ lookup阶段的字段。即 users 表对应的主键。 $lookup在from集合的文档中对localField和foreignField执行相等的匹配。 * "foreignField" 表示 指定from集合中文档中的字段。即 users_roles 表对应的外键 * "as" 表示 指定要添加到输入文档中的新数组字段的名称。 */ Users.aggregate([ { "$project": { "__v": 0 } }, { "$match": { "id": id } }, { $lookup: { from: 'users_roles', localField: "id", foreignField: "user_id", as: "users_roles" } } ]) .then( user => { console.log(user) }) .catch(err => { console.log(`${err.name} : ${err.message}`) })

 

 三张表!!!

  • 【 需求:
  • 【 思路:已知用户角色表 users_roles["user_id"] = 3,其中三张表中的关联如下,用户角色表 users_roles 与 角色权限表 role_permission:users_roles["role_id"]  = role_permission["role_id"] ,角色权限表 role_permission 和 权限表 permission:role_permission["permission_id"] = permission["id"]  】
  • 【 三张表在数据库中的字段定义如下: 】

mongodb锁表fsync lock mongodb 临时表_Mongodb_19

mongodb锁表fsync lock mongodb 临时表_mongoose_20

mongodb锁表fsync lock mongodb 临时表_数据库_21

let id = 3; 

/**
* 聚合(aggregate)主要用于处理数据,并返回计算后的数据结果,有点类似sql语句中的 count(*)
* "$project" 只显示(1)或隐藏(0)对应属性
* "$match" 用于过滤数据,只输出符合条件的文档,此处是 只输出 id=3 的数据
* "$lookup" 根据主外键联表查询(外键是相对主表中的字段名,此处是 user_id)
*           "from" 表示 在同一数据库中指定要执行联接的集合。
*           "localField" 表示 指定从文档输入到$ lookup阶段的字段。如 users_roles 表对应的主键。 $lookup在from集合的文档中对localField和foreignField执行相等的匹配。
*           "foreignField" 表示 指定from集合中文档中的字段。如 role_permission 表对应的外键
*           "as" 表示 指定要添加到输入文档中的新数组字段的名称。
*/
UsersRoles.aggregate([
    { "$match": { "user_id": id } },
    {
      $lookup: {
        from: 'role_permission',
        localField: "role_id",
        foreignField: "role_id",
        as: "inventory_permission"
      }
    }, {
      $lookup: {
        from: 'permission',
        localField: "inventory_permission.permission_id",
        foreignField: "id",
        as: "permission_detail"
      }
    }
  ])
.then( user => { 
    console.log(user) 
})
.catch(err => {
     console.log(`${err.name} : ${err.message}`)
})

 

 

总结:

  • 1、首先建立mongodb数据库和数据表,可以通过可视化工具 Robo 3T
  • 2、然后运行node服务器项目,选择Mongoose操作数据库(Mongoose 是MongoDB的一个对象模型工具)
  • 3、通过 mongoose 连接数据库,定义数据表模型(需要的字段在此定义,若没定义获取不到)
  • 4、然后通过 mongoose 在 node.js 中的语法,操作数据库,参考官方文档
  • 5、写给自己的随笔,有问题欢迎指出(Θ▽Θ)