2017-09-02 92 views
2

下降之前當集合不存在時drop()被稱爲存在,拋出一個錯誤:檢查集合中的貓鼬

ns not found

目前我使用類似

try { 
    await MongooseModel.collection.drop(); 
} catch (err) { 
    if (err.message !== 'ns not found') { 
     throw err; 
    } 
} 

這味道不太好。我們並不清楚爲什麼首先會拋出一個錯誤,我認爲drop()將返回false,如果它不存在,就像它在Mongo控制檯中完成一樣。

如果只有對Mongoose模型的參考MongooseModel

在我正在做這件事的地方,我沒有對連接對象的引用,就像在this answer中建議的那樣。

回答

3

其實你有參考。在建立連接後,您可以隨時撥打mongoose.connection並返回當前連接。

您還可以簡單地從任何模型實例中獲取db。因此,如果您不想在集合不存在時針對錯誤try..catch,則可以使用的一種方法是基本上使用底層驅動程序中的.listCollections()方法,以查看您想要訪問的集合實際上是否存在於名稱空間中第一:

const mongoose = require('mongoose'), 
     Schema = mongoose.Schema; 

mongoose.Promise = global.Promise; 
mongoose.set('debug',true); 

const uri = 'mongodb://localhost/blank', 
     options = { useMongoClient: true }; 

const testSchema = new Schema({},{ strict: false }); 

const ModelA = mongoose.model('ModelA', testSchema); 
const ModelB = mongoose.model('ModelB', testSchema); 

(async function() { 

    try { 

    const conn = await mongoose.connect(uri,options); 


    await ModelB.create({ a: 1 }); 


    for (let model of [ModelA,ModelB]) { 

     let list = await model.db.db.listCollections({ 
     name: model.collection.name 
     }).toArray() 
     //console.log(JSON.stringify(list,undefined,2)); 

     if (list.length !== 0) { 
     await model.collection.drop(); 
     } else { 
     console.log('collection %s does not exist',model.collection.name); 
     } 

    } 


    } catch(e) { 
    console.error(e); 
    } finally { 
    mongoose.disconnect(); 
    } 

會證明,首先嚐試收集降不存在,而不發出一個錯誤:

Mongoose: modelbs.insert({ a: 1, _id: ObjectId("59aa9cfe581cca7afac55181"), __v: 0 }) 
collection modelas does not exist 
Mongoose: modelbs.drop() 

還有其他事情可以做,比如使用.collection(){ strict: true }底層驅動程序首先獲得一個集合對象。但是,這真的只是「拋出一個錯誤」。因此,儘管在發佈.drop()之前「知道」該收藏不存在,但它仍然與try..catch需要的處理相同。

因此,如果沒有錯誤,請首先檢查收集的存在。當然,沒有別的東西會消除它。但你可能應該總是錯誤處理以防萬一。


我個人覺得它只是清潔允許發生異常,然後簡單地檢查細節,看到被提出的例外是我所期望的:

for (let model of [ModelA,ModelB]) { 
    try { 
    await model.collection.drop(); 
    } catch (e) { 
    if (e.code === 26) { 
     console.log('namespace %s not found',model.collection.name) 
    } else { 
     throw e; 
    } 
    } 
} 

在這種情況下code: 26"Namespace not found",在這種情況下會出現這種情況,或者在使用本地.collection()方法的情況下也會出現{ strict: true }。但是使用集合對象的現有句柄的.drop()要短得多。

要點是沒有什麼要求您實際記錄異常,並且「檢查異常」(即在批量插入中預期有重複鍵錯誤)是常見操作。只需測試預期的錯誤代碼,並且「如果」返回其他內容,則可以在更高的級別提升異常。

如前所述,儘管您可以假設如果您要求數據庫按名稱列出集合並且它存在於結果中然後存在,最安全的過程仍然是從I/O如果在「查詢」和「操作」之間有其他修改需要刪除。

+0

謝謝。 '(await model.db.db.listCollections({name:...})。toArray()).length'確實可行,但對於這樣一個基本的和需要的任務來說是非常麻煩的。 try ... catch看起來不太好,因爲應該對它的消息聲明錯誤(這是它的通用MongoError)。希望有更好的方法。 – estus

+0

@estus我的一般情況是簡單地執行'.drop()'操作,但期望可以爲「找不到命名空間」引發異常。除此之外的任何事情,那麼你「恐慌!」。它通常是最乾淨和最安全的方式。對此添加了更詳細的解釋。 –

+0

謝謝,通過代碼做到這一點確實更清潔。 – estus