一、問題描述
通過NodeJs操作MongoDb數(shù)據(jù)庫,在刪除操作中使用主鍵id做為條件:

有接觸過mongodb的都知道這里的id是要傳入ObjectId對象的,不能直接傳字符串類型。
但是我在此處將字符串id轉(zhuǎn)換成ObjectId時,卻報如下錯誤:
UnhandledPromiseRejectionWarning: Error: Argument passed in must be
a single String of 12 bytes or a string of 24 hex characters
二、問題分析
查詢官網(wǎng),可以通過以下幾種方式將String轉(zhuǎn)換為ObjectId:
1、使用ObjectId(id)
2、使用new ObjectId(id)?
3、使用靜態(tài)方法ObjectId.createFromHexString(id)
然而使用以上三種方法依然出現(xiàn)上述錯誤。
但是直接使用id變量的值"5c640413d63e990b8478f6fd"來轉(zhuǎn)換時是正常的:
deleteOne({_id:ObjectId("5c640413d63e990b8478f6fd")})?
難道id變量和常量有什么不同嗎?打印id變量類型,確實為string,顯示的字符串內(nèi)容也一樣。
查看錯誤提示,代碼調(diào)用堆棧如下:

找到objectid.js對應(yīng)源碼:

可以看到是長度不對。
打印id變量長度,以及各個字符值:


id變量字符串開頭和結(jié)尾各多了一對單引號,這是怎么來的呢?
于是理一下數(shù)據(jù)流程,從數(shù)據(jù)源頭開始查找。最早這個id是從數(shù)據(jù)庫中查找的,經(jīng)調(diào)試此時還是object類型,且轉(zhuǎn)成string類型后長度是24,說明這時候是正常的。之后在界面中使用模板時傳遞參數(shù)過程出現(xiàn)了數(shù)據(jù)轉(zhuǎn)換:
1、界面 home.art:
<a href='delete_interface/<%=items[i]._id %>'>
經(jīng)測試此時_id轉(zhuǎn)成string長度還是24
2、接口映射 app.js:
app.get('/delete_interface/:id',delete_interface)
經(jīng)測試此時傳入delete_interface的參數(shù)id字符串長度為26,數(shù)據(jù)轉(zhuǎn)換過程中發(fā)生了變化!
三、問題解決
模板代碼中在傳遞參數(shù)前將id變量從object類型轉(zhuǎn)換成string類型
<a href='delete_interface/<%=items[i]._id.toString() %>'>
測試傳入delete_interface的參數(shù)id字符串長度為24,數(shù)據(jù)庫刪除操作沒有再報錯,問題解決。
需要注意要在傳參前進行類型轉(zhuǎn)換,在delete_interface拿到參數(shù)后再進行轉(zhuǎn)換是沒用的。
四、總結(jié)
分析問題時,
1、不要被表面現(xiàn)象迷惑,比如查看id字符串內(nèi)容看不出問題,但是查看長度及字符ascii碼則明顯能看出來
2、查看錯誤日志,分析錯誤堆棧,查看源碼
3、分析代碼和數(shù)據(jù)經(jīng)過流程