MongoDB 數(shù)據(jù)庫
MongoDB 的數(shù)據(jù)邏輯結(jié)構(gòu):文檔(document)、集合(collection)、數(shù)據(jù)庫(database)。
- 文檔(document):由鍵值對(duì)構(gòu)成,相當(dāng)于關(guān)系數(shù)據(jù)庫中的一行記錄。
- 集合(collection):多個(gè)文檔組成一個(gè)集合,相當(dāng)于關(guān)系數(shù)據(jù)庫的表。
- 數(shù)據(jù)庫(database):多個(gè)集合邏輯上組織在一起,就是數(shù)據(jù)庫。
一個(gè) MongoDB 實(shí)例支持多個(gè)數(shù)據(jù)庫(database)。

使用 mongoose 連接 MongoDB
MongoDB 數(shù)據(jù)庫基礎(chǔ):
- mongoose 中的一切由 schema(?skēm?) 開始。 schema 是一種以文件形式存儲(chǔ)的數(shù)據(jù)庫模型骨架,并不具備數(shù)據(jù)庫的操作能力。
- Schema 定義了 model 中的所有屬性,而 model 則是對(duì)應(yīng)一個(gè) MongoDB 中的 collection。
Schema 生成 Model,Model 創(chuàng)造 Entity,Model 和 Entity 都可對(duì)數(shù)據(jù)庫操作造成影響,但 Model 比 Entity 更具操作性。
連接數(shù)據(jù)庫
連接數(shù)據(jù)庫,實(shí)現(xiàn)增、刪、改、查操作
// 引入 mongoose 模塊
const mongoose = require('mongoose');
// 定義數(shù)據(jù)庫地址
// uri:mongodb://+[用戶名:密碼@]+數(shù)據(jù)庫地址[:端口]+數(shù)據(jù)庫名
// uri:mongodb://user:pass@localhost:port/database
const uri = 'mongodb://user:pass@localhost:port/database?authSource=admin';
// 連接 mongoDB 數(shù)據(jù)庫
mongoose.connect(uri, {useNewUrlParser: true});
const db = mongoose.connection;
// 將連接綁定到錯(cuò)誤事件
db.on('error', console.error.bind(console, 'MongoDB connection error'));
// 錯(cuò)誤事件,同上
db.on('error', function(error) {
console.error.bind(console, '數(shù)據(jù)庫連接失?。? + error);
});
// 一次打開事件
db.once('open', function() {
console.log('一次打開記錄');
});
// 數(shù)據(jù)庫連接成功
db.on('open', function() {
console.log('數(shù)據(jù)庫連接成功');
});
// 數(shù)據(jù)庫連接失敗
db.on('disconnected', function() {
console.log('數(shù)據(jù)庫連接斷開');
});
// 斷開連接
mongoose.disconnect();
Schema
// 定義 Schema
const Schema = mongoose.Schema;
// 使用 Schema 構(gòu)造函數(shù),創(chuàng)建一個(gè)新的 Schema 實(shí)例
// 實(shí)例化 mongoose.Schema 對(duì)象并定義 Model 的屬性
const ArticleScheme = new Schema({
title: String,
author: String,
content: String,
publishTime: Date
});
// 將 Schema 注冊(cè)成 Model
mongoose.model('Article', ArticleScheme);
// 如果 Model成功注冊(cè),就可以通過如下方式訪問模型
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() 方法,查詢所有符合要求的數(shù)據(jù)
// findOne() 方法,查詢符號(hào)要求的第一條數(shù)據(jù)
ArticleModel.find({title:'node.js'}, function(err, docs) {
if (err) {
console.log('error');
return;
}
console.log('result: ' + docs); // 打印實(shí)體
// 【查詢紀(jì)錄后,修改記錄的值】
docs[0].title = 'javascript'; // 修改數(shù)據(jù)
docs[0].save(); // 保存修改后的數(shù)據(jù)
// 【刪除數(shù)據(jù)】
if (docs) {
// 遍歷文檔,逐條刪除
docs.forEach(function(ele) {
// 只有單個(gè)文檔可以使用 remove() 方法
ele.remove();
})
}
})
可以將 Model 提取成單獨(dú)的一個(gè)類:
??
強(qiáng)烈建議在每個(gè)模型模塊(文件)中,定義每個(gè)模型綱要,導(dǎo)出方法以創(chuàng)建模型。
article.js
// 導(dǎo)入 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}
});
// 導(dǎo)出模型
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 },
});
// 導(dǎo)出模型
module.exports = mongoose.model('Farmer', FarmerSchema);
// --------
// 引入并使用
const FarmerModel = require('../model/farmers');
增(Create)
通常所說的 CRUD 就是數(shù)據(jù)庫的增(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 保存到數(shù)據(jù)庫
FarmerEntity.save(function(err, docs) {
if (err) {
console.log('create error: ' + err);
}
console.log('create success:\n ' + docs);
});
Model.insertMany(),一次插入多個(gè)值
// 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(),查詢所有符合要求的數(shù)據(jù)
FarmerModel.find({ name: '張三' }, function(err, docs) {
if (err) {
console.log('查詢錯(cuò)誤' + err);
return;
}
console.log('打印實(shí)體:result: ' + docs);
});
// 從集合/表中按照 uuid 鍵值對(duì)查找文檔(document)
db.getCollection('NaturalPersonInfo').find({uuid:'8a033c7f20ea2bdea3c4b9d60d42f11e'})
Model.findOne(),查詢符號(hào)要求的第一條數(shù)據(jù)
Model.findById()
改(Update)
Model.update()
// Model.update()
// 查詢 uuid 為 2234567890 的實(shí)體,將他的名字改為張團(tuán)團(tuán),允許更新多條查詢記錄
FarmerModel.update({ uuid: '2234567890' }, { name: '張團(tuán)團(tuán)' }, { multi: true }, function(err, docs) {
if (err) {
console.log('更新錯(cuò)誤' + err);
return;
}
console.log('更新后的實(shí)體:result: ' + docs);
});
Model.updateMany(),一次更新多條數(shù)據(jù)。
Model.updateOne(),一次更新一條數(shù)據(jù)。
Model.findByIdAndyUpdate(),
Model.findOneAndUpdate()
刪(Delete)
Model.remove(),刪除
FarmerModel.remove({ uuid: '1234567890' }, function(err, docs) {
if (err) {
console.log('查詢錯(cuò)誤' + err);
return;
}
console.log('刪除成功');
});
Model.findByIdAndRemove()
Model.findOneAndRemove()
常見錯(cuò)誤
1. 連接 MongdDB 數(shù)據(jù)庫時(shí)提示字符串參數(shù)失效
示例代碼:
// 連接 mongoDB 數(shù)據(jù)庫
mongoose.connect(uri, function(err) {
if (err) {
console.log('connect failed' + err);
return;
}
console.log('connect success');
});
錯(cuò)誤提示內(nèi)容:
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.
解決方法:連接時(shí)傳遞參數(shù):
// 連接 mongoDB 數(shù)據(jù)庫
mongoose.connect(uri, {useNewUrlParser: true}); // <——
const db = mongoose.connection;
// 將連接綁定到錯(cuò)誤事件
db.on('error', console.error.bind(console, 'MongoDB connection error'));
2. 連接 MongoDB 數(shù)據(jù)庫時(shí)授權(quán)失敗,提示:errmsg: 'Authentication failed.', code: 18
// uri 后面添加 authDatabase 參數(shù)
mongoose.connect('mongodb://user:password@host:port/dbname?authSource=admin')
解決參考:Authentication in mongoose using SCRAM-SHA-1