Mongoose 常用API及常見問題彙總

最近又在用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() 區別
  1. update比find之後save()效率高,因爲這樣不用讀取整個文檔。
  2. Mongoose的update是MongoDB的update,但是Mongoose的save可能是MongoDB的插入或是update。
  3. 關於save,mongoose會自動diff新文檔,只更改更新部分。這有利於原子性。
  4. 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的相關的操作還有很多,在這裏不詳細列舉了,至於常見問題可能會隨時更新,做下記錄~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章