前言 之前自己做專案時都是使用MySQL搭配居多,公司是使用Node,也因為公司需求最近開始踏上MongoDB學習之旅,此篇文章我主要紀錄的是後面的小方法可以帶出來的功能,CRUD的部分就不特別寫。
Node套件部分 以Node來說常見的套件我知道有兩個,而今天主要是來整理mongoose的一些用法。
mongodb 這個是官方提供的套件,有提供一整套蠻詳細的使用方法。最近也開始練習直接看官方文件~
mongoose 很多剛開始寫mongodb的人應該最多人是使用mongoose,我的感覺是ODM的方式讓他在管理上很淺顯易懂吧。
ODM是什麼?=> Object Document Mapping 跟MySQL的ORM是同樣的意思
_於是又會問ORM是什麼? => Object Relational Mapping 簡單來說是: 把資料庫操作轉成抽象的程式碼物件的使用方式 在google上面搜尋一下都有蠻清楚的解釋可看
一些mongoose語法紀錄 .lean() ⇒ 讓回傳回來的資料容量變小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const schema = new mongoose.Schema({ name : String });const MyModel = mongoose.model('Test' , schema);await MyModel.create({ name : 'test' });const sizeof = require ('object-sizeof' );const normalDoc = await MyModel.findOne();const leanDoc = await MyModel.findOne().lean();sizeof(normalDoc); sizeof(leanDoc);
來源
.exec() ⇒ 其實用法有三種差異,我這邊用query Posts來測試
Posts.findOne({name:'chi'})
=> return a Query {} 如果要取用裡面資料會需要再使用.then((doc)=>{})
把資料抓出來
Posts.findOne({name:'chi'}).then()
=> return a Promise {} 假議題,就是上面的用法用.then來接
Posts.findOne({name:'chi'}).exec()
=> return a Promise {} 也是回傳promise,那跟上面有什麼不同? 如果沒有用async/await,exec()返回來的資料也是要用.then把資料抓出來,他的優點在於其他地方:
如果出現error更好的追蹤是在你程式碼哪一行出錯
回傳的promise是fully-fledged promise
什麼是fully-fledged promise? 1.使用.exec()執行出來的程式碼是真的Promise,Promise所有的方法都有。 2.而上面1程式碼是queries,然後可以使用.then()來接,但.then()接出來的資料不是真正的Promise,有些Promise原生的方法像catch, finally,這邊都不能使用。 來源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 app.get('/test' , async (req, res) => { const query = Posts.findOne({ name : 'chi' }) const promise = Posts.findOne({ name : 'chi' }).exec() const then = Posts.findOne({ name : 'chi' }).then() try { assert.ok(!(query instanceof Promise )) assert.ok(promise instanceof Promise ) assert.ok(then instanceof Promise ) } catch (e) { console .log(e) } return 'ok' })
以上是為了測試他本身回傳回來的東西,但現在我們基本上都一定會搭配async/await來寫程式碼(對吧!!),如果是使用async/await都會成功回傳資料的,差別還是在於我剛列出來的那兩點,1 .exec()可以追蹤錯誤程式碼 => 是建議使用.exec()的喔2 .exec()回傳真正的promise
1 2 3 4 5 6 const query = await Posts.findOne({ name : 'chi' })const promise = await Posts.findOne({ name : 'chi' }).exec()
1 2 3 4 5 6 7 { "_id" : "6190c61ede7ec25305b1f563" , "name" : "chi" , "title" : "Post 1" , "__v" : 0 }
官方解釋,我就是個翻譯仔
.select() ⇒ 選取特定欄位query出來,裡面有其他用法,可以傳遞參數的方式有很多, 所以用法上也很彈性,可以看到比較多不同的寫法。 直接貼官方code來偷懶。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 query.select('a b' ); query.select(['a' , 'b' ]); query.select({ a : 1 , b : 1 }); query.select('-c -d' ); const schema = new Schema({ foo : { type : String , select : false }, bar : String }); query.select('+foo' ); query.select({ a : 1 , b : 1 }); query.select({ c : 0 , d : 0 });
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Model.find({username : user.username}, 'first last' , function (err, docs ) { }); Model.find({username : user.username}, '-first -last' , function (err, docs ) { }); Model.find({username : user.username}) .select('first last' ) .exec() Model.select(['first' , 'last' ]); Model.select({ first : 1 , last : 1 });
官方
其他來源
.sort() ⇒ 排序
1 2 3 4 5 6 7 8 9 10 Model.find().sort({_id :1 }) Model.find().sort({_id :-1 }) Model.sort({ field : 'asc' , _id : -1 }); Model.sort('field -test' );
官方來源 其他來源
創建Schema時可用expires來設定過期時間(TTL) 過期後,該筆資料自動刪除
1 2 3 4 5 6 7 8 const mongoose = require ('mongoose' );const schema = new mongoose.Schema({ code : { type : String , index : true }, created_at : { type : Date , default : Date .now, expires : 60 * 5 }, }); module .exports = mongoose.model('sl2_captchas' , schema);
來源
紀錄 目前常碰到的是這幾個,之後如果有碰到別的用法將持續更新。
Author:
Chi Lin
Permalink:
https://chiderlin.github.io/2021/11/26/MongoDB-learning/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY ?