最近又在用express+Mongoose,爲方便之後查詢及問題彙總,在這裏簡單記錄下
安裝和鏈接
npm install mongoose
Mongoose基本概念
Schema: 表定義模板
Model: 類似關係數據庫表,封裝成具有一些集合操作的對象
let schema = new mongoose.Schema({
id: {
type: Number,
required: true
},
name: {
type: String,
required: true
},
age: {
type: Number
}
}, {
versionKey: false,
timestamps: {
createdAt: 'createTime', updatedAt: 'updateTime', lastLoginDate: 'lastLoginDate'
}
});
let userModel = mongoose.model('user', schema);
常用API
一說到數據庫,最先想到的就是增刪改查。
新增
Model.create(): 插入一個或多個文檔
Model.create(docs[, options][, callback])
如果插入一個文檔,則傳入一個對象即可;如果插入多個文檔,則傳入一個數組
let doc = {
id: 1,
name: 'shan-er',
age: 1
};
userModel.create(doc, (error) => {})
ModelEntity.save():只針對當前文檔實例
Document.prototype.save([options][, callback])
let doc = {
id: 1,
name: 'shan-er',
age: 1
};
let mongooseEntity = new userModel(doc);
mongooseEntity.save((error) => {})
Model.insertMany()
Model.insertMany(docs[, options][, callback])
多條數據插入,將多條數據一次性插入,相對於循環使用create保存會更加快。
Mongoose 在向 MongoDB 發送 insertMany 之前會驗證每個文檔。因此,如果一個文檔出現驗證錯誤,則不會保存任何文檔,除非將 ordered 選項設置爲 false。
let docs = [{
id: 1,
name: 'shan-er',
age: 1
}, {
id: 2,
name: 'shan-er-2',
age: 1
}];
userModel.insertMany(docs, (error, docs) => {})
create()與save()區別
Model.create()內部調用了<model_instance>.save()方法,並且做了一些額外的封裝。
兩者主要的區別在於:
-
Model.create()可以同時保存一組文檔。
-
.save()只針對當前文檔實例。
create(docs) 爲 docs 中的每個文檔執行 MyModel(doc).save()。
查找
Model.find()
Model.find(conditions, [fields], [options], [callback])
userModel.find({age: 1}, (err, docs) => {
// docs 是查詢的結果數組
})
userModel.find({}, ['id','name'], (err, docs) => {
// docs 此時只包含文檔的部分鍵值
})
Model.findOne()
Model.findOne([conditions], [projection], [options], [callback])
與 Model.find 相同,但只返回單個文檔
userModel.findOne({age: 1}, (err, doc) => {
// doc 是單個文檔
})
Model.findById()
Model.findById(id, [projection], [options], [callback])
與 findOne 相同,但它接收文檔的 _id 作爲參數,返回單個文檔。_id 可以是字符串或 ObjectId 對象。
userModel.find(obj._id, (err, doc) => {
// doc 是單個文檔
})
修改
Model.Update()
Model.update(conditions, doc, [options], [callback])
conditions:查詢條件;doc:需要修改的數據,不能修改主鍵(_id);options:控制選項;
該方法會匹配到所查找的內容進行更新,返回數據處理條數;
userModel.update({name: 'shan-er'}, {$set : {age : 2}, {upsert : true}, (err) => {})
Model.findOneAndUpdate()
Model.findOneAndUpdate([conditions], [update], [options], [callback])
該方法會根據查找去更新數據庫,返回處理後的數據
需要獲取數據就用findOneAndUpdate(),只需要修改數據而不關注修改後數據那就用update()
Model.findByIdAndUpdate()
Model.findByIdAndUpdate(id, [update], [options], [callback])
Model.updateMany():一次更新多條
Model.updateMany(conditions, doc, [options], [callback])
Model.updateOne(): 一次更新一條
Model.updateOne(conditions, doc, [options], [callback])
options說明
options有以下選項:
new: bool - 默認爲false。返回修改後的數據。
upsert: bool - 默認爲false。如果不存在則創建記錄。
fields: {Object|String} - 選擇字段。類似.select(fields).findOneAndUpdate()。
maxTimeMS: 查詢用時上限。
sort: 如果有多個查詢條件,按順序進行查詢更新。
runValidators: 如果值爲true,執行Validation驗證。
setDefaultsOnInsert: 如果upsert選項爲true,在新建時插入文檔定義的默認值。
passRawResult: 如果爲真,將原始結果作爲回調函數第三個參數。
.save()和update() 區別
- update比find之後save()效率高,因爲這樣不用讀取整個文檔。
- Mongoose的update是MongoDB的update,但是Mongoose的save可能是MongoDB的插入或是update。
- 關於save,mongoose會自動diff新文檔,只更改更新部分。這有利於原子性。
- update不能觸發中間件,validation默認不能,但是可以修改。
刪除
Model.remove()
Model.remove(conditions[, options][, callback])
remove方法有兩種使用方式,一種是用在模型上,另一種是用在模型實例上.
從集合中刪除所有匹配 conditions 條件的文檔
Model.findOneAndRemove()
Model.findOneAndRemove(conditions[, options][, callback])
Model.findByIdAndRemove()
Model.findOneAndRemove(id[, options][, callback])
Model.deleteOne()
Model.deleteOne(conditions[, options][, callback])
刪除符合 conditions 條件的第一條文檔。
Model.deleteMany()
Model.deleteMany(conditions[, options][, callback])
刪除所有符合 conditions 條件的文檔。
remove與deleteMany的區別
一樣的效果,返回值不一樣。
remove()並不會真正釋放空間。需要繼續執行 db.repairDatabase() 來回收磁盤空間。
官方建議使用deleteOne()、deleteMany()
常見問題彙總
用Mongoose得到的對象不能增加屬性
原因:
因爲Mongoose是個ODM (Object Document Mapper),類似於操作關係型數據庫使用的ORM(Object Relational Mapper),我們使用Mongoose取到的數據的結構是要依賴於我們定義的schema結構的。增加的屬性在schema中沒有定義,所以我們在取到的結果中增加某個屬性是無效的。
方法一:在Schema中增加屬性
增加屬性:一是直接增加屬性值,入庫;二若不想入庫,可以增加virtual屬性
schema.virtual('fullName').get(function () {
return this.firstName + this.lastName;
});
// 獲取vitual屬性,兩種方式獲取
// 1. doc._doc.fullName 獲取
// 2.
// userModel.set('toObject', {virtuals: true});
// userModel.set('toJSON', {virtuals: true});
方法二:clone對象
自動給集合名增加”s”
官網定義API
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-eCnK7Mop-1585216619242)(mongoose/s.jpg)]
collection名稱應該爲第三個參數,若爲缺省,會自動根據參數name的值以複數形式生成collection
let userModel = mongoose.model('user', schema, 'user');
小結
mongoose的相關的操作還有很多,在這裏不詳細列舉了,至於常見問題可能會隨時更新,做下記錄~