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

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容