0%

Node.js_使用 mongoose 连接 MongoDB 数据库

MongoDB 数据库

MongoDB 的数据逻辑结构:文档(document)、集合(collection)、数据库(database)。

  • 文档(document):由键值对构成,相当于关系数据库中的一行记录。
  • 集合(collection):多个文档组成一个集合,相当于关系数据库的表。
  • 数据库(database):多个集合逻辑上组织在一起,就是数据库。

一个 MongoDB 实例支持多个数据库(database)。

MongoDB 数据库结构

使用 mongoose 连接 MongoDB

MongoDB 数据库基础:

  • mongoose 中的一切由 schema(ˈskēmə) 开始。 schema 是一种以文件形式存储的数据库模型骨架,并不具备数据库的操作能力。
  • Schema 定义了 model 中的所有属性,而 model 则是对应一个 MongoDB 中的 collection

Schema 生成 ModelModel 创造 EntityModelEntity 都可对数据库操作造成影响,但 ModelEntity 更具操作性。

连接数据库

连接数据库,实现增、删、改、查操作

// 引入 mongoose 模块
const mongoose = require('mongoose');

// 定义数据库地址
// uri:mongodb://+[用户名:密码@]+数据库地址[:端口]+数据库名
// uri:mongodb://user:pass@localhost:port/database
const uri = 'mongodb://user:pass@localhost:port/database?authSource=admin';

// 连接 mongoDB 数据库
mongoose.connect(uri, {useNewUrlParser: true});
const db = mongoose.connection;

// 将连接绑定到错误事件
db.on('error', console.error.bind(console, 'MongoDB connection error'));

// 错误事件,同上
db.on('error', function(error) {
  console.error.bind(console, '数据库连接失败:' + error);
});

// 一次打开事件
db.once('open', function() {
    console.log('一次打开记录');
});

// 数据库连接成功
db.on('open', function() {
  console.log('数据库连接成功');
});

// 数据库连接失败
db.on('disconnected', function() {
  console.log('数据库连接断开');
});

// 断开连接
mongoose.disconnect();

Schema

// 定义 Schema
const Schema = mongoose.Schema;
// 使用 Schema 构造函数,创建一个新的 Schema 实例
// 实例化 mongoose.Schema 对象并定义 Model 的属性
const ArticleScheme = new Schema({
    title: String,
    author: String,
    content: String,
    publishTime: Date
});
// 将 Schema 注册成 Model
mongoose.model('Article', ArticleScheme);

// 如果 Model成功注册,就可以通过如下方式访问模型
const ArticleModel = mongoose.model('Article');

// 通过 Model 定义 Entity
var ArticleEntity = new ArticleModel({
    title: 'node.js',
    author: 'node',
    content: 'node.js is great!',
    publishTime: new Date()
});

// 【将文档插入到集合中】
ArticleEntity.save(function(err) {
    if (err) {
        console.log('save failed ' + err);
    }else {
        console.log('save successed');
    }
});

// 【查询】
// find() 方法,查询所有符合要求的数据
// findOne() 方法,查询符号要求的第一条数据
ArticleModel.find({title:'node.js'}, function(err, docs) {
    if (err) {
        console.log('error');
        return;
    }
    console.log('result: ' + docs); // 打印实体

    // 【查询纪录后,修改记录的值】
    docs[0].title = 'javascript'; // 修改数据
    docs[0].save(); // 保存修改后的数据

    // 【删除数据】
    if (docs) {
        // 遍历文档,逐条删除
        docs.forEach(function(ele) {
            // 只有单个文档可以使用 remove() 方法
            ele.remove();
        })
    }
})

可以将 Model 提取成单独的一个类:

💡

强烈建议在每个模型模块(文件)中,定义每个模型纲要,导出方法以创建模型。

article.js

// 导入 mongoose 模块
const mongoose = require('mongoose');

// 定义 Schema
const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId; // 主键

const ArticleSchema = new Schema({
    id: ObjectId,
    title: {type: String, required: true, max: 100},
    name: {type: String, required: true, max: 100},
    date: {type: date}
});

// 导出模型
module.exports = mongoose.model('Article', ArticleSchema);

farmers.js

const mongoose = require('mongoose');

// 定义 Schema
const Schema = mongoose.Schema;
const FarmerSchema = new Schema({
  uuid: { type: String, required: true },
  name: { type: String, required: true },
  id_number: { type: String, required: true },
  phone: { type: String, required: true },
  public_key: { type: String, required: true },
  private_key: { type: String, required: true },
});

// 导出模型
module.exports = mongoose.model('Farmer', FarmerSchema);

// --------
// 引入并使用
const FarmerModel = require('../model/farmers');

增(Create)

通常所说的 CRUD 就是数据库的增(Create)删(Delete)查(Read)改(Update)。

Model.create()

const doc = ({
  uuid: '1234567890',
  name: '张三',
  id_number: '320321201810104321',
  phone: '15812345678',
  public_key: 'publickey',
  private_key: 'privatekey',
});

FarmerModel.create(doc, function(err, docs) {
  if (err) {
    console.log('create error: ' + err);
    return;
  }
  console.log('create success:\n ' + docs);
});

Entity.save()

// 通过 Model 定义 Entity
const FarmerEntity = new FarmerModel({
  uuid: '2234567890',
  name: '李四',
  id_number: '320321201810104322',
  phone: '15912345678',
  public_key: 'publickey_1',
  private_key: 'privatekey_1',
});

// 将 Entity 保存到数据库
FarmerEntity.save(function(err, docs) {
  if (err) {
    console.log('create error: ' + err);
  }
  console.log('create success:\n ' + docs);
});

Model.insertMany(),一次插入多个值

// insertMany()
FarmerModel.insertMany([{
  uuid: '12345',
  name: '王五',
  id_number: '123456',
  phone: '123456',
  public_key: '12345',
  private_key: '12345',
}, {
  uuid: '12345',
  name: '赵六',
  id_number: '123456',
  phone: '123456',
  public_key: '12345',
  private_key: '12345',
}], function(err, docs) {
  if (err) {
    console.log('create error: ' + err);
  }
  console.log('create success:\n ' + docs);
});

查(Read)

Model.find(),查询所有符合要求的数据

FarmerModel.find({ name: '张三' }, function(err, docs) {
  if (err) {
    console.log('查询错误' + err);
    return;
  }
  console.log('打印实体:result: ' + docs);
});

// 从集合/表中按照 uuid 键值对查找文档(document)
db.getCollection('NaturalPersonInfo').find({uuid:'8a033c7f20ea2bdea3c4b9d60d42f11e'})

Model.findOne(),查询符号要求的第一条数据

Model.findById()

改(Update)

Model.update()

// Model.update()
// 查询 uuid 为 2234567890 的实体,将他的名字改为张团团,允许更新多条查询记录
FarmerModel.update({ uuid: '2234567890' }, { name: '张团团' }, { multi: true }, function(err, docs) {
  if (err) {
    console.log('更新错误' + err);
    return;
  }
  console.log('更新后的实体:result: ' + docs);
});

Model.updateMany(),一次更新多条数据。

Model.updateOne(),一次更新一条数据。

Model.findByIdAndyUpdate()

Model.findOneAndUpdate()

删(Delete)

Model.remove(),删除

FarmerModel.remove({ uuid: '1234567890' }, function(err, docs) {
  if (err) {
    console.log('查询错误' + err);
    return;
  }
  console.log('删除成功');
});

Model.findByIdAndRemove()

Model.findOneAndRemove()

常见错误

1. 连接 MongdDB 数据库时提示字符串参数失效

示例代码:

// 连接 mongoDB 数据库
mongoose.connect(uri, function(err) {
    if (err) {
        console.log('connect failed' + err);
        return;
    }
    console.log('connect success');
});

错误提示内容:

DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.

解决方法:连接时传递参数:

// 连接 mongoDB 数据库
mongoose.connect(uri, {useNewUrlParser: true}); // <——
const db = mongoose.connection;
// 将连接绑定到错误事件
db.on('error', console.error.bind(console, 'MongoDB connection error'));

2. 连接 MongoDB 数据库时授权失败,提示:errmsg: ‘Authentication failed.’, code: 18

// uri 后面添加 authDatabase 参数
mongoose.connect('mongodb://user:password@host:port/dbname?authSource=admin')

解决参考:Authentication in mongoose using SCRAM-SHA-1

参考

  • 开源框架:node-mongode-native
  • 开源框架:mongoose
  • 开源框架:egg-mongoose
  • mongoose 官网 | Doc
  • Express 教程 3: 使用数据库 (Mongoose)
  • CNode:Mongoose 学习参考文档 —— 基础篇 ⭐️⭐️⭐️
  • Mongoose 增查改删学习笔记 ⭐️⭐️⭐️
  • Node 学习记录: mongodb

欢迎关注我的其它发布渠道