用toObject()取代lean() -TypeError: lean is not a function


Posted by sophiayu86 on 2023-01-03

為何傳進樣板引擎的變數無法用.key取值?

 const url = new Url({
    original_url: original_url
     });
 return url.save()
 .then((link) => {
    res.render("success", { link });
    })
 .catch((error) => console.log(error));

奇怪,link確定有傳進success.handlebars,因為可以用{{link}}在頁面上印出link裡面的東西,長這樣:
{
original_url: 'uuu',
_id: new ObjectId("63b152ee75f7725fb76f0fc2"),
__v: 0
}

但為何改成{{link.original_url}}會抓不到東西?

Error message說:

Handlebars: Access has been denied to resolve the property "password" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details

原來.save() return回來的promise裡面是Mongoose Document,不是純 json 物件, 所以拿不到物件key值。

聽說有個厲害的.lean()方法可以把Mongoose Document轉成純 json 物件:

        const url = new Url({
          original_url: original_url
        });
        return url
        .save()
        .lean()                          //加入這行
        .then((link) => {
          res.render("success", { link });
          })
        .catch((error) => console.log(error));

Error: TypeError: lean is not a function

怎麼會這樣?!!!!

原來.lean()方法,不支援 .save() 方法!

悲劇。

Solution 1: 只好把要用的東西存成變數,用參數傳進handlebars template

Solution 2: 可是還是想用.lean()把Mongoose Document轉成純 json 物件怎麼辦?

小撇步:先用個.find(), return回來的 Query object 就可以接.lean(), 這樣用handlebars 就抓得到{{link.original_url}} 了!可是這樣多用一個.find()對效率好像不算一件好事…

        const url = new Url({
          original_url: original_url
          });
        const id = url._id.toHexString();
        return url
        .save()
        .then(() => {
          return Url.findById(id).lean();
          })
        .then((link) => {
          res.render("success", { link });
          })
        .catch((error) => console.log(error));

Solution 3: 其實還有一個.toObject() 的方法可以把Mongoose Document轉成純 json 物件!


        const url = new Url({
          original_url: original_url
        });
        url.save()
        .then(()=> {return url.toObject()})
        .then((link) => {
          res.render("success", { link });
          })
        .catch((error) => console.log(error));

結論:lean()不能用時,就試試toObject()吧!


#Mongoose #Handlebars







Related Posts

透過瀏覽器傳送資料的方式與限制

透過瀏覽器傳送資料的方式與限制

D35_W4 HW1 + HW2

D35_W4 HW1 + HW2

為什麼「class」可以放兩個以上的名稱?

為什麼「class」可以放兩個以上的名稱?


Comments