此文已由作者黃鍇授權網易雲社群釋出。
歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。
前言
由於Mongoose一直沒有中文文件,加上現在市面上充斥著太多“快速上手”,很多中文文件都只盲目介紹了Mongoose的API用法(但是現在升級後,很多API發生了變化),沒有做詳細介紹,導致很多人用了半天的Mongoose,還是對其一知半解(比如我!),因此寫了這篇文章,從以下三個角度聊聊Mongoose。
是什麼(what?)
為什麼?(why?)
怎麼用(how?)
快速上手
再深一點(這才是細嚼慢嚥的關鍵哦)
本文閱讀可快,可慢全憑喜好。但本著貪多嚼不爛的想法,還是希望客觀慢慢品嚐。
是什麼(what)?
首先,必須要知道Mongoose是什麼
Mongoose(狐獴)就是圖上這個小可愛。(學名:Suricata suricatta),頭尾長42-60釐米,是一種小型的哺乳動物……
好像有點跑題。當然,今天介紹的Mongoose不是真的小動物,而是一款在Node.js環境下對MongoDB API 進行便捷操作的物件模型工具(所以理論上,我預設你是需要大概懂MongoDB資料庫才會來用這個的)。
要特別強調的是,我這裡說它是物件模型工具,說明Mongoose的操作是以物件為單位的。
同時,由於Mongoose升級後(差不多)全面支援Promise,可以很方便的對接async/await語法。因此接下來的我的程式碼都會預設使用Promise形式。
為什麼(Why)?
我們知道,MongoDB官網提供了一個Node.js環境下的MongoAPI,那為什麼我還需要使用Mongoose呢?當然是因為它提供了一些官方不能提供的功能,如它官網介紹的:
Let's face it, writing MongoDB validation, casting and business logic boilerplate is a drag.
可以看出,Mongoose主要是減輕我們在寫資料驗證,業務邏輯模板的負擔。同時,由於Mongoose一直強調它是一個MongoDB物件建模工具,因此在這裡就必須要提出Mongoose的核心,也是Mongoose困擾人已久的一個東西——模式和模型。
模式?模型?
對於Mongoose的新人來說,最頭疼的就是它裡面有關模式(Schema),模型(Model)的概念。Mongoose的一切都始於一個模式。這點和MongoDB基於集合(Collection)的思路可能不太一致,因為本身MongoDB是無模式的,也正是因為它的無模型,導致其使用起來極具靈活性。
那Mongoose為什麼要定義一個模型?Why Define a Mongoose Schema? 給出瞭解釋:
have you ever wondered how to pull these random documents out and figure out which properties were saved to document? The truth is that for 90% of your web applications you’ll be using model classes and you’ll have a standard set of fields you’ll be expecting to be saved to your database
模式有模式的好處,生活中絕大部分的資料是遵循一定的模式的,模式能讓我們規範資料的表現形式,不至於太隨心所欲。同時模式給我們提供了很多資料驗證的便利(這就像我們討論JavaScript弱型別和TypeScript強型別是一樣一樣的)。
同時,由於Mongoose使用的依然MongoDB而非關係型資料庫,因此它沒有完全失去其天生的靈活性,它依然開放了讓你可以定義任意欄位的能力。
// Defining a schema on a Mongoose model// that allows storage of arbitrary fields// Mongoose.schema(schemaObject, options)var User = Mongoose.schema({
username: String,
password: String}, {
strict: false});複製程式碼
注意到上面程式碼的第二個欄位,你把strict設定為false,你就能在這個模型中加入任意欄位了(但是還是不建議這樣做,因為這意味著你需要自己去做資料的驗證)。
如果你實在不習慣使用 模式,可以使用MongoDB官方的API。
與其說Mongoose定義模式是多此一舉的,不如說,它在靈活性的基礎上,提供了更安全的模型化操作物件的方式。
我個人感覺:使用Mongoose你更有操作物件的感覺。
模式 VS 模型
我們已經知道了模式是有其優勢的,那為什麼我還需要模型?這兩個有什麼區別?
官方的定義:Each schema defines the shape of the documents within that collection.
模式
模式它是一個 抽象的概念。其實可以把模式考慮成設計規範 ,定義了設計圖紙應該如何畫,預設單位是多少,如果沒有該規範,那每個人畫的設計圖紙就是各式各樣,沒法真正投入建造。
模型
模型相對於模式是具體的概念,可以把模型考慮成設計圖紙 :按照設計規範畫出一個圖紙,任何人根據該規範就可以把房子造出來。
例項
而模型的例項才是真正的我們住的房子,在MongoDB裡也就是文件(document)
多此一舉?
你可能會說,何必多此一舉,把模式和模型合起來不就好了嘛?很多人喜歡這樣寫:
const studentModel = Mongoose.model('Student', new Mongoose.Schema({ name: String, sex: String});複製程式碼
這樣寫也可以,但是這個前提是你確定你的模式只在這一個模型中使用。之所以有個模式這個抽象概念,就像設計規範, 它從來不是說只能在一張圖紙中使用,你可以利用這個規範繪製出很多符合規範的圖紙。
有時候你可能會有這樣的需求,基本一樣的資料結構,但是我需要建多個不同集合,或者稍微修改一下模式,新建一個新的集合,這時候把模式獨立出來,你就會發現省事很多了。
const personSchema = new Mongoose.Schema({ name: String, sex: String});const studentModel = Mongoose.model('Student', personSchema);const otherStudentModel = Mongoose.model('OtherStudent', personSchema);const teacherSchema = personSchema.clone();
teacherSchema.add({ teach: String});const teacherModel = Mongoose.model('Teacher', teacherSchema);複製程式碼
舉例
再來舉一個例子:假設,我們建立了一個寵物貓咪樂園,我們需要去招集一批寵物喵成為我們的會員。但是呢,我們的宣傳員他沒見過喵(多麼神奇的生物)。於是,我們絞盡腦汁,合計出一個規範:所有的寵物貓應該滿足三個屬性name,type, meow。也就是說,寵物喵必須要有名字,必須有一個品種,同時它必須要會“喵喵”叫!
const catSchema = new Mongoose.Schema({ name: String, type: String,meow: Boolean});複製程式碼
好了,現在我們把規範告訴他,但是他說他記性不好。怕忘記,因此我們制定了一個叫《寵物貓咪指南1.0》的手冊
const CatGuide = Mongoose.model('Animal', catSchema);複製程式碼
好了,宣傳員開心的出去了,開始到處撩貓去了,把所有它認為是貓的生物都記錄下來:
const kitty1 = new CatGuide({ name: 'mimi', type: 'American Shorthair', meow: true });const kitty2 = new CatGuide({ name: 'kaddy', type: 'American Shorthair', meow: true });const doggy = new CatGuide({ name: 'doggy', type: 'Dog!!', meow: false });
……複製程式碼
(但是這個不靠譜的,拿著手冊也能找錯,找了一隻穿貓咪衣服的狗!!?)
因此,我們只把那兩隻貓儲存到資料庫裡。
kitty1.save().then(() => console.log('meow'));
kitty2.save().then(() => console.log('meow'));複製程式碼
知道了他們之間的關係,剩下的就好辦了。就是程式設計了,程式設計能解決的事情都是簡單的事情。
怎麼用(How)?
快速開始
Mongoose的使用流程很簡單:
連線 ——> 定義模式 ——> 生成Model ——> 生成Model例項複製程式碼
其中,連線,Model,例項是實際跟資料庫打交道的,他們之間的關係如下:
通過一個很簡單的例子,我們就可以上手操作MongoDB,然後配合官方API,熟練的人可以直接跳過了,但是如果你想了解更多細節,可以繼續看下去,看看每個操作具體還可以怎麼配置。
// step 1 引入Mongooseconst Mongoose = require('Mongoose');// setp2 建立連線Mongoose.connect('MongoDB://localhost/test');// step3 建立模式const catSchema = new Mongoose.Schema({ name: String, type: String });// step4 生成模型const Cat = Mongoose.model('Cat', catSchema);// step5.1 模型直接操作documentCat.create({ name: 'mimi', type: 'American Shorthair' }).then(...)// or
// step5.2 生成例項,操作documentconst kitty = new Cat({ name: 'mimi', type: 'American Shorthair' });
kitty.save().then(() => console.log('meow'));複製程式碼
連線
我們都知道,使用資料庫的第一步是需要連上資料庫,Mongoose提供了一個很簡單的方式連線:connect。
Mongoose.connect(url, [options]);複製程式碼
注意,現在使用url需要加上 { useNewUrlParser: true }選項,否則可能會報錯。 Mongoose.connect(url, { useNewUrlParser: true });
其中url引數的完整形式,跟MongoDB連線字串的一致:MongoDB://username:password@host:port/database?options...
預設情況下,使用者名稱和密碼可以省略:
Mongoose.connect('MongoDB://localhost/db1');複製程式碼
如果還需要傳遞使用者名稱、密碼,則可以使用如下方式
Mongoose.connect('MongoDB://username:password@host:port/database?options...');複製程式碼
connect()方法還接受一個選項物件options,該物件將傳遞給底層驅動程式。這裡所包含的所有選項優先於連線字串中傳遞的選項:
bufferCommands : 這個選項會關閉Mongoose的快取機制 ,再深一點章節會說。
user/pass :使用者名稱和密碼
autoIndex :通常MongoDB會自動生成索引,但是有時候如果你不需要,可以把這個選項設定為false
dbName :制定資料庫名,一般是沒辦法在連線字串中指定的情形( MongoDB+srv 語法連線到 MongoDB Atlas)
還有一些選項是用來配置Mongoose的,例如,我之前說的useNewUrlParser ,還有 pooleSize, bufferMaxEntries,connectTimeoutMS, socketTimeoutMS…… 這些都是比較高階的配置,一般人用不到。如果真的需要用到,可以翻官方文件
模式
我們知道,模式其的是規範的作用,因此定義模式主要是定義我們資料的表現形式以及做一些格式約定,方便自動校驗。例如,我建立了一個學生的模式,它規定了name和age欄位的型別:
const studentSchema = new Mongoose.Schema({
name: String,
age: Number,
});複製程式碼
基本型別
模式有以下10種基本型別,如果只使用基本型別,就輸入以下欄位就行
String | Number | Date | Buffer | Boolean | Schema.Types.Mixed | Schema.Types.ObjectId | Array | Schema.Types.Decimal128 | Map(新加入的ES6的Map)
注意:1. 如果是Array,可以使用[]代替,你可以可以規定Array內部資料型別,例如數字陣列: [Number]。2. 很多人困惑為什麼沒有Object型別,如果你想定義物件,使用Schema.Types.Mixed就行了。Mixed型別支援多種型別混合,比如陣列套物件,物件套陣列……
額外約束
但是,只規定了基本型別還不夠,我想做一些額外的約束,比如姓名長度,年齡大小。因此每種型別還有很多配置項,如果要使用額外的約束,需要使用Object形式,同時,型別通過type引入:
const studentSchema = new Mongoose.Schema({
name: { type: String, minlength: 2 },
age: { type: Number, min: 12, max: 16},
});複製程式碼
這裡只介紹一些比較常用的,更多使用說明參考官方手冊:
所有型別可用:
required: boolean or function, 很好理解,如果為真就表示該欄位必須要存在
default: Any or function, 設定預設值
validate: function, 增加一個校驗函式
字串 String:
lowercase/upppercase: boolean, 是否做大小寫處理
trim: boolean, 是否去除首尾空格
match: RegExp, 只有滿足特定正則的值才能被接受
enum: Array, 只有陣列內的值才被接受
minlength/ maxLength: Number, 最小、大長度
數字 Number / 日期 Date
min / max: Number / Date (根據型別),必須滿足的最大值/最小值
注意: Date使用的是內建的Date,但是你使用setMonth等內建的方法,不會被Mongoose不會識別到,因此使用doc.save()不會有效果。你必須設定doc.markModified(pathToYourDate)。
const Assignment = Mongoose.model('Assignment', { name: String, dueDate: Date });const a = new Assignment({ name: 'test', dueDate: Date.now() });
a.save().then(callback);
Assignment.findOne({ name: 'test' }, 'name dueDate', (err, doc) => {
doc.dueDate.setMonth(3);
doc.save(callback); // THIS DOES NOT SAVE YOUR CHANGEdoc.markModified('dueDate');
doc.save(callback); // works});複製程式碼
模型
有了模式之後,就可以生成模型了,生成模型很簡單,就使用model函式就行了。
// step3 建立模式const catSchema = new Mongoose.Schema({ name: String, type: String });// step4 生成模型const Cat = Mongoose.model('Cat', catSchema);複製程式碼
注意,雖然所有的例子都是Mongoose.model,但是實際上model是Connect原型的方法:Connection.prototype.model(),即一個連線例項才有model方法。(具體的可以看後面的 再深一點章節)
其中,model第一個引數就是collection名稱(Mongoose會自動 複數化,想修改名稱也請看後面章節),同時model會把Schema裡的內容複製一份
官方原文是說複製一份
The .model() function makes a copy of schema. Make sure that you've added everything you want to schema before calling .model()!
但是我實際測試,感覺還是引用,在呼叫model方法之後,通過add(), remove()方法修改Schema依然會影響之前建立的model。
const catSchema = new Mongoose.Schema({ name: String, type: String });const Cat = Mongoose.model('Cat', catSchema);
catSchema.remove('type'); // 在建立model後修改Schema會影響之前的modelconst kitty = new Cat({ name: 'mimi2', type: 'American Shorthair' });
kitty.save().then(() => console.log('meow')); // type欄位不會儲存到資料庫複製程式碼
例項
根據之前的圖可以知道,model的例項就是文件,有一些比較方便的操作方法,更多方法參考文件:
get(path,opt) : 獲取文件的某個欄位,這個函式比較好的是做資料處理,第2個引數可以將該欄位轉換成其他型別:«Schema|String|Number|Buffer|*»
doc.get('age') // 47
// dynamic casting to a string
doc.get('age', String) // "47"複製程式碼
save():顧名思義儲存文件到資料庫
var Tank = Mongoose.model('Tank', yourSchema);var small = new Tank({ size: 'small' });
small.save(function (err) { if (err) return handleError(err); // saved!});複製程式碼
set(path, value, opt) : 設定文件的某個欄位,第三個引數依然可以修改欄位型別,同時,可以設定{ strict: false }新增任意欄位(回顧 為什麼章節)
// 簡單用法doc.set(path, value)// 物件形式用法,修改多個欄位doc.set({
path : value
, path2 : {
path : value
}
})// 把value通過Number進行轉換doc.set(path, value, Number)// 填加任意欄位doc.set(path, value, { strict: false });複製程式碼
CRUD操作
由於對文件的操作通常是在"集合"這個維度,因此大部分的操作都是在model上完成的,除了一些單文件的操作可以在文件這個維度,通過例項完成
新增文件[s]
文件儲存有三種方法,除了之前介紹的save方法,還可以使用模型的下面兩種方法。
model.create(object) : 其實就是new model.save()的簡寫
model.insertMany([object]) : 可以批量增加,從記憶體寫到資料庫比較實用
區別就像例項的save是貓主人自己跑過來報名。create,insertMany就是我們工作人員替使用者直接錄入。
const catSchema = new Mongoose.Schema({ name: String, type: String });const Cat = Mongoose.model('Cat', catSchema);
Cat.create({ name: 'mimi', type: 'American Shorthair' }).then(...) // 插入單條文件Cat.insertMany([{ name: 'mimi', type: 'American Shorthair' }...]).then(...) // 插入多條文件複製程式碼
查詢文件
Mongoose的查刪改的使用方法基本大同小異,這裡重點介紹一下查詢,剩下的更新和刪除主要介紹方法,不會具體介紹怎麼使用
跟查詢有關的方法有…一堆(ByID那一批我排除了,實際用途不大,很多時候我們都不知道文件的_id):
大部分都大同小意,然後findOne跟find的差別就是,一個是查詢所有滿足條件的文件,一個是隻返回第一個,因此我這裡只講一個find的用法:
Modle.find.(conditions, [projection], [options], [callback] )複製程式碼
conditions «Object» : 查詢條件(完全跟MongoDB手冊一致)
[projection] «Object|String» : 選取欄位,和下面的select方法完全一致(我推薦使用鏈式呼叫)
[options] «Object» : 查詢配置(在再深一點章節再介紹)
[callback] «Function» : 推薦使用Promise寫發,不寫callback
一般來說,查詢MongoDB中的某個文件,是需要一個查詢條件(condition)的,這個查詢條件可以簡單可以複雜,由於完全跟MongoDB手冊一致,本文畢竟不是《MongoDB入門》這裡就不做過多敘述,如果後續有時間會把整理的MongoDB手冊發上來, 下面的例子也會說明一些。
這裡重點說一下Mongoose自身提供的一些比較使用的方法,這裡舉官方一個例子來說明一下:
通常一個標準的MongoDB的查詢大概是這樣(其中Person是一個model),Mongoose完全支援這種查詢方式:
Person.
find({ // 這裡寫查詢條件
occupation: /host/, // 查詢條件可以用正則
'name.last': 'Ghost', // 限定name.last
age: { $gt: 17, $lt: 66 }, // 限定年齡範圍
likes: { $in: ['vaporizing', 'talking'] } // 限定喜好必須要在這個陣列中
}).
limit(10). // 限定取出的文件條數
sort({ occupation: -1 }). // 針對某個欄位排序,1表示正序,-1表示逆序
select({ name: 1, occupation: 1 }). // 選擇取出的欄位,1表示取出,0表示不取出,如果不需要id,需要顯式寫{_id : 0}
exec(callback); // 這裡使用then也行,完全支援Promise,但是查詢不是Promise,這個要注意,後面會說複製程式碼
但是Mongoose把 常用的方法都提取出來了,例如:where,gt,lt,in……(完整API文件),因此更推薦使用下面這種方式:
// Using query builderPerson.
find({ occupation: /host/ }).
where('name.last').equals('Ghost').
where('age').gt(17).lt(66).
where('likes').in(['vaporizing', 'talking']).
limit(10).
sort('-occupation').
select('name occupation').
exec(callback);複製程式碼
要強調一下,查詢支援promise一些語法,但是它不是promise。這個坑必須要記得!! 千萬不要將callback形式和promise混用!
例如,下面的query可以執行三次!並不會因為一次then或者callback結束。 說明then只是一個執行方法,查詢並不是真正的Promise。
const q = MyModel.updateMany({}, { isDeleted: true }, function() { console.log('Update 1'); }); q.then(() => console.log('Update 2')); q.then(() => console.log('Update 3'));複製程式碼
如果要統計查詢的文件資料,可以使用countDocuments(),用法和MongoDB的count()一致
Person.find(...)
.count()
.then() // 這裡獲得的是一個數字複製程式碼
注意: Mongoose的count()已經被廢棄,需要統計個數得用countDocuments
更新文件
更新文件的方法有下面三個,condition的使用方法和find的方法一完全一致(包括where那些查詢方法都可以使用),只是要注意, update只是更新欄位(符合Schema),但是replace是完全的用新doc來替換。
刪除文件
刪除文件主要是兩個方法,使用方法完全和查詢一致。
再深一點
細品連線
快取機制
根據上面的例子,你會發現一個奇怪的現象, 我們並沒有判斷連線是否成功就進行了操作?這是因為Mongoose內部快取了函式呼叫。
Mongoose lets you start using your models immediately, without waiting for Mongoose to establish a connection to MongoDB
這很cool,很方便,我們不用去關心連線成功再去增加文件,否則你必須要這樣:
Mongoose
.connect('MongoDB://localhost/test')
.then(() => { const catSchema = new Mongoose.Schema({ name: String, type: String }); const Cat = Mongoose.model('Cat', catSchema); const kitty = new Cat({ name: 'mimi', type: 'American Shorthair' });
kitty.save().then(() => console.log('meow'));
})
.catch(err => console.log(err));複製程式碼
但是這樣會帶來一個問題就是你如果不建立連線,進行操作也不會收到任何提示。
var MyModel = Mongoose.model('Test', new Schema({ name: String }));// Will just hang until Mongoose successfully connectsMyModel.findOne(function(error, result) { /* ... */ });
setTimeout(function() {
Mongoose.connect('MongoDB://localhost:27017/myapp');
}, 60000);複製程式碼
所以一定要養成良好的喜歡,在做查詢,刪除等操作的時候,判斷一下是否已經連線。判斷連線可以使用下面提的 connection物件的連線狀態碼
connection物件
說實話,剛開始使用Mongoose的時候我總是充滿疑惑,一開始我認為Mongoose應該是一個類,它代表一次連線,通過new的方式可以建立一個資料庫的連線。但是Mongoose不是,它直接通過connect方法就建立了一個連線,就能直接運算元據庫上的集合,那說明這個Mongoose只是一個例項(的確也是)。那如果Mongoose只是一個例項,它就等於那一個連線嗎?那為什麼Mongoose上面沒有運算元據庫的方法?而且我要如何建立多個連線呢?一個個問題在腦海中迴盪,腦子裡早已一團漿糊,於是,還是回到了官方文件找答案。
其實,每次執行Mongoose.connect,實際就是建立了一個Connection物件(這個物件可以通過Mongoose.connection獲得)這個物件才是真正對應的一個資料庫的連線。因此,所有的資料庫操作其實都是在connect物件中,例如:createCollection(), dropCollection(), dropDatabase() ……
這個connection物件同時可以監聽幾個常用事件:connected,disconnected,error。
const connection = Mongoose.connection;
connection.on('connected', () => { console.log('Mongoose connection open');
connection.createCollection('test').then(() => console.log('add collection')),
});複製程式碼
連線狀態碼
為了方便檢視物件的狀態,connection也提供了一個readyState屬性,可以方便判斷當前連線狀態,通過Mongoose.STATES能獲取readyState的所有取值:
{ '0': 'disconnected',
'1': 'connected',
'2': 'connecting',
'3': 'disconnecting',
'99': 'uninitialized',
disconnected: 0,
connected: 1,
connecting: 2,
disconnecting: 3,
uninitialized: 99 }複製程式碼
所以,理論上你可以這樣判斷連線是否建立
if (Mongoose.STATES[connection.readyState] === 'connected') ....複製程式碼
多個連線
同時,如果你想建立多個連線,你可以使用Mongoose.createConnection()的方式建立一個新的連線,引數什麼的和connect一致,剩下的操作一致。例如以下這個官方例子:
var Mongoose = require('Mongoose');var db = Mongoose.createConnection(..);
db.model('Venue', new Schema(..));var Ticket = db.model('Ticket', new Schema(..));var Venue = db.model('Venue');複製程式碼
細品模式
虛屬性
虛屬性(Virtuals)是Mongoose提供的一個很有用的功能,它可以方便我們儲存一些不需要儲存在資料庫中的資料。例如,我儲存一個使用者的姓名,只需要存名和姓:
const personSchema = new Schema({
name: {
first: String,
last: String
}
}); const Person = Mongoose.model('Person', personSchema); const voidsky = new Person({
name: { first: 'void', last: 'sky' }
});複製程式碼
但是我在讀出的時候,需要列印使用者的全名,當然我們可以這樣做:
console.log(voidsky.name.first + ' ' + voidsky.name.last); // void sky複製程式碼
但是虛屬性提供了一個更方便的方式:
personSchema.virtual('fullName').get(function () { return this.name.first + ' ' + this.name.last;
});console.log(voidsky.fullName);複製程式碼
如果你用過一些前端框架,你可以把它當作計算屬性。但是這個屬性不會被持久化到MongoDB中,虛擬函式有get和set的方法,熟悉setter和getter的就應該知道,一樣一樣的。
虛屬性還提供了一個很有用的Aliases欄位,它可以把Schema的某個屬性完全跟一個虛屬性進行連線(set和get的繫結),你操作這兩個屬性的效果完全一致,這個好處是你可以在儲存的時候節約空間,但是獲取資料的時候,使用語義化的描述 。只是Aliases定義的屬性不會被持久化到資料庫。這裡看官方案例:
const personSchema = new Schema({
n: {
type: String,
alias: 'name' // 注意這裡,等於建立了一個name的虛屬性,繫結到n
}
});const Person = Mongoose.model(personSchema);const person = new Person({ name: 'Val' });console.log(person); // { n: 'Val' }console.log(person.toObject({ virtuals: true })); // { n: 'Val', name: 'Val' }console.log(person.name); // "Val"person.name = 'Not Val';console.log(person); // { n: 'Not Val' }複製程式碼
子模式
schema是可以巢狀的,如果我們需要定義一個複雜的結構,可以使用巢狀的方式(通常子模式會配置成{ _id: false },具體可以參考下面的模式配置)
const childSchema = new Schema({
n: {
type: String,
alias: 'name'
}
}, { _id: false });const parentSchema = new Schema({ // If in a child schema, alias doesn't need to include the full nested path
c: childSchema,
name: {
f: {
type: String, // Alias needs to include the full nested path if declared inline
alias: 'name.first'
}
}
});複製程式碼
模式配置
schema是有很多配置的,你可以在定義Schema的時候配置,或者使用set方法。
new Schema({..}, options);// orconst schema = new Schema({..});
schema.set(option, value);複製程式碼
相關配置可以參考文件,這裡舉例幾個可能會用到的:
colleciton 這個配置可以修改collection的名字(預設是使用model的複數化名稱,見下面)
const dataSchema = new Schema({..}, { collection: 'data' });const dataModel = Mongoose.model('othername', dataSchema);複製程式碼
模式方法
(未完待續)
額外推薦:視覺化客戶端
當然,你可以通過命令列檢視結果,但是更多人還是習慣使用圖形化的介面,這裡推薦一個MongoDB的視覺化客戶端:robot 3T,這就是原來大名鼎鼎的RoboMongo。全平臺都支援。要是之前我還真不想推薦它,因為在mac上顯示實在難受,不支援retina螢幕。
但是現在,已經好了很多
更多網易技術、產品、運營經驗分享請點選。
相關文章:
【推薦】 Spring Cloud使用總結