[Mongo] Mongoose 操作
- Mongoose 會追蹤在與 DB 連線前對資料庫進行的請求,並在連線後加以執行。
- Mongoose 是 MongoDB 的 ODM(Object Data Modeling) 套件,可以讓我們更方便處理 CRUD。
- 透過 mongoose 的使用,我們可以更像在操作 relational database。
安裝
$ npm install --save mongoose
基本使用
與 MongoDB 建立連線
// ./app.js
const mongoose = require('mongoose');
/**
* 與 mongoDB 建立連連
* mongoose.connect('mongodb://[資料庫帳號]:[資料庫密碼]@[MongoDB位置]:[port]/[資料庫名稱]')
* mongoDB 預設的 port 是 27017,這裡可以省略
* todo 是 database 的名稱,當 app 執行時,mongoose 會自動建立這個 database
*/
mongoose.connect('mongodb://localhost:27017/todo', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
// 取得資料庫連線狀態
const db = mongoose.connection;
db.on('error', (err) => console.error('connection error', err)); // 連線異常
db.once('open', (db) => console.log('Connected to MongoDB')); // 連線成功
建立 Schema(資料庫綱要)
- schema 是用 JSON 的方式來告訴 mongo 說 document 的資料會包含哪些型態。
// ./models/Animal.js
const mongoose = require('mongoose');
let AnimalSchema = new mongoose.Schema({
size: String,
mass: Number,
category: {
type: String,
default: 'on land',
},
name: {
type: String,
required: true,
},
createdAt: {
type: Date,
default: Date.now,
},
});
// 添加 instance method (給 document 用的方法)
AnimalSchema.methods.getCategory = function () {
// 這裡的 this 指透過這個 function constructor 建立的物件
console.log(`This animal is belongs to ${this.category}`);
};
// 添加 instance method 的另一種寫法
AnimalSchema.methods('getName', function () {
console.log(`The animal is ${this.name}`);
});
// Compile Schema 變成 Model,如此可以透過這個 Model 建立和儲存 document
// 會在 mongo 中建立名為 animals 的 collection
module.exports = mongoose.model('Animal', AnimalSchema);
使用建立好的 Model 來新增 Document
// ./app.js
const Animal = require('./models/Animal');
// 建立 document
const elephant = new Animal({
category: 'on land',
mass: 6000,
size: 'big',
name: 'Lawrence',
});
// 直接存取 elephant 這個 instance 的 type
console.log(elephant.category); // "on land"
// 透過在 Model 中定義的 instance methods 取得 elephant 的 category
elephant.getCategory(); // "This animal is belongs to on land"
// 儲存 document
// 透過
elephant.save((err, animal) => {
if (err) {
return console.error(err);
}
console.log('document saved');
db.close(); // 結束與 database 的連線
});
Model
這裡都是 Schema 已經 compile 成 Model 後可使用的方法:
const Animal = mongoose.model('Animal', AnimalSchema);
CREATE
一次建立一個 document
/**
* document.save(callback(err, document))
**/
const elephant = new Animal({
type: 'elephant',
size: 'big',
color: 'gray',
mass: 6000,
name: 'Lawrence',
});
elephant.save((err, elephant) => {
if (err) {
return console.error(err);
}
// 第二個參數 elephant 指的是儲存好的 document
});
一次建立多個 document
keywords: create
, insertMany
- 可以在
create
後帶入陣列亦可新增多筆 documents,但使用insertMany
的效能會更好
/**
* Model.insertMany(dataToCreate, callback(err, documents))
* 第二個參數指的是透過 create 建立起來的 documents
*/
const animalData = [
{
type: 'mouse',
color: 'gray',
mass: 0.034,
name: 'Marvin',
},
{
type: 'nutria',
color: 'brown',
mass: 6.35,
name: 'Gretchen',
},
{
type: 'wolf',
color: 'gray',
mass: 45,
name: 'Iris',
},
];
Animal.insertMany(animalData, (err, animals) => {
if (err) {
return console.error(err);
}
});
DELETE
/**
* collection.deleteOne(conditions, options, callback)
*/
await Animal.deleteMany(); // 刪除 Animal 中的所有 documents
await Animal.deleteMany({ color: 'red' });
Model.deleteMany(), Model.deleteOne() @ mongoose
READ
/**
* Model.find(condition, projection, options, callback(err, documents))
* 回傳 "query"
*/
// 回傳 Animal 中的所有 documents
Animal.find({}, (err, animals) => {
if (err) {
return console.error(err);
}
console.log(animals);
});
// 透過 query 尋找特定的 documents
Animal.find({ size: 'big' }, (err, animals) => {
if (err) {
return console.error(err);
}
animals.forEach((animal) => {
console.log(`${animal.name}: ${animal.type}`);
});
});
// 使用正規式尋找
Animal.find({ name: /^fluff/ }, callback(err, documents));
/**
* 進階用法
*/
Animal.find({}, null, { sort: { createdAt: -1 } }, (err, animals) => {
// -1 表示 descending orders
});
Animal.find({})
.sort({ createdAt: -1 })
.exec(function (err, animals) {
if (err) {
return console.error(err);
}
res.json(animals);
});
使用 async … await
的寫法:
const getTodos = async () => {
const query = Todo.find();
const documents = await query.exec(); // query.exec return a promise
console.log('documents', documents);
};
其他可用的 query 方法:
Model.findById(id, [projection], [options], [callback(err, documents)]);
Model.findOne(
[questionCondition],
[projection],
[options],
[callback(err, doc)],
);
- Queries @ Mongoose Guide
- Queries @ Mongoose API
- Collection Methods @ MongoDB