Mongoose-modified-at
是一款自動更新字段變化時間並記錄到數據庫中的 Mongoose
插件,類似 Mongoose
自帶的 timestamps
功能。
使用場景
讓我們考慮一個場景,我們有個文章發佈與展示的需求,數據模型如下。
const schema = new mongoose.Schema({
// 文章標題
title: String,
// 是否爲草稿
is_draft: Boolean,
// 是否推薦
is_recommended: Boolean,
// 更多字段...
})
當我們在展示最新文章列表時,應該是以文章第一次發佈的時間倒序展示,因爲文章可以存爲草稿,多次編輯,所以不能用 Mongoose
提供的 createdAt
或 updatedAt
作爲第一次發佈的時間,正確的做法是在每次文章創建或更新時,確定用戶是發佈文章而不是存爲草稿,然後記錄此次時間,用該時間作爲第一次發佈的時間。
要實現該功能我們需要在代碼邏輯層進行處理,這樣可行不過有點耦合,或者自己封裝一個 Mongoose
中間件來做這件事,不過現在你可以把這件事交給一個經受測試、API
優雅的插件 ModifiedAt
來處理。
首先安裝插件。
npm install mongoose-modified-at --save
然後在 Schema
初始化時做簡單的配置即可,如下。
import modifiedAt from 'mongoose-modified-at'
// 在 mongoose.model 調用之前
schema.plugin(modifiedAt, {
// 函數名將作爲字段名寫入數據庫
publishedAt(doc) {
// 當函數返回值爲 true 時,則記錄該時間
return !doc.is_draft
},
// 推薦文章也是如此
recommendedAt(doc) {
return doc.is_recommended
},
})
const Article = mongoose.model('Article', schema)
當文檔保存或更新攜帶着 is_draft
字段並且值爲 false
時,插件就會記錄此次時間到你聲明的 publishedAt
字段上一起寫入數據庫。
示例如下:
await Article.create({
title: 'Document Title',
is_draft: false,
is_recommended: true,
// 更多字段...
})
結果如下(數據庫):
{
"title": "Document Title",
"is_draft": false,
"is_recommended": true,
"publishedAt": ISODate("2019-09-27T03:11:07.880Z"),
"recommendedAt": ISODate("2019-09-27T03:11:07.880Z"),
// 更多字段...
}
API介紹
上面是 ModifiedAt
的富 API
形式,即對象格式,全部參數選項如下。
schema.plugin(modifiedAt, {
// 設置監聽字段
fields: ['name', 'status', 'another'],
// 設置後綴
suffix: '_your_suffix',
// 設置路徑默認行爲
select: true,
// 自定義字段
customField(doc) {
// 做一些你想做的事,然後返回 Boolean 值,告訴插件是否記錄時間
},
})
🍎 參數解釋:
-
fields
: 設置監聽字段,在文檔創建或更新時,如果存在被監聽的字段,則自動以字段名 + 後綴
的形式做爲字段,並記錄此次更新時間到該字段上。可選,Array
類型。 -
suffix
: 設置後綴,默認值爲_modifiedAt
。可選,String
類型。 -
select
: 設置路徑默認行爲,默認爲true
,參考 Mongoose 文檔。可選,Boolean
類型。 -
customField
: 自定義字段,此字段不會加後綴,以函數形式添加到參數中,用於自定義功能,函數接收唯一文檔參數,當函數返回值爲真值時,則記錄此次時間到該字段上。
簡化API
🚀 爲了增加 API
的簡潔易用同時避免過度重載,ModifiedAt
只增加了一種簡化傳參格式,如下。
schema.plugin(modifiedAt, ['name', 'status'])
意思是將 fields
選項提取出來作爲參數,寫入數據庫的結果如下。
{
"name": "Tom",
"status": 1,
"name_modifiedAt": ISODate("2019-09-27T03:13:17.888Z"),
"status_modifiedAt": ISODate("2019-09-27T03:13:17.888Z"),
}
支持異步
你需要 Node.js
版本支持 async/await
即可。
import P from 'bluebird'
const petSchema = new mongoose.Schema({
name: String,
age: Number,
sex: String,
// 1:表示採購中,2:已購買,3:已售出
status: Number,
})
petSchema.plugin(modifiedAt, {
// 記錄購買於哪時
async boughtAt(doc) {
// 延時 1s
await P.delay(1000)
return doc.status === 2
},
// 記錄售出於哪時
soldAt(doc) {
return doc.status === 3
},
})
支持 Mongoose 4.x
如果你現在使用的是 Mongoose 4.x,那麼你需要使用插件 1.x 版本,文檔可在這裏查看。
npm install mongoose-modified-at@1 --save
“100%”測試覆蓋率
29
個測試用例,777
行代碼,“100%”
測試覆蓋率。
細節
更多細節處理請移步至 GitHub 文檔,這裏。
最後
1、支持一下,煩請點個 Star 吧,貢獻就點個 Fork 吧 😘
2、本文同步發表於凹凸實驗室博客或微信公衆號,歡迎關注我們,麼麼噠 😍