iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
自我挑戰組

被MongoDB用Aggregate暴打的後端小菜雞日記系列 第 5

被MongoDB用Aggregate暴打的後端小菜雞日記-day5-轉變資料格式

  • 分享至 

  • xImage
  •  

今天要來介紹一下,我之前在使用$match搜尋時,踩到的雷點,資料型態不同!!
就像數字1和文字"1",對我們來說看起來一樣,但程式在運行判讀會是不一樣的值,因為類似的原因,導致我搜尋不到想要的資料。

第一個雷點是,每一個document的_id資料格式是ObjectId,雖然表面上看"507f191e810c19729de860ea"就像是一個文字字串,但實際上它算是mongodb會自動產生的特殊資料型態,包含timestamp、隨機亂碼...等資訊,有興趣的話可以參考官方的說明

例如:我們回傳很多商品資料給前端,顯示一整列的商品列表給顧客,顧客對某一項商品有興趣,會點進去單一商品的詳細頁面,此時前端就會傳商品的id給後端,要這筆商品的資料,通常這時傳入的資料型態都是字串。

如果你找這筆商品資料

{
  _id: "507f191e810c19729de860ea",
  name: "鍵盤",
  price: 4560,
  amount: 11
}

這樣下搜尋指令會找不到資料,只會得到空陣列

product.aggregate([
  { $match: { _id: "507f191e810c19729de860ea" } }
]);

要解決這個問題,有兩種做法
一個是先用mongodb內建的函式ObjectId(),將文字轉換成ObjectId格式再帶入。

product.aggregate([
  { $match: { _id: ObjectId("507f191e810c19729de860ea") } }
]);

另一個方式是,將document的_id轉換成文字的資料型態,此時就會用到$toString這個操作符,將特定欄位的資料格式轉換成文字,同時搭配$addFields(新增欄位)這個操作符。

使用方式如下,這樣就可以正常搜尋到想要的商品資料

product.aggregate([
  { $addFields: { _id: { $toString: "$_id" } } },
  { $match: { _id: "507f191e810c19729de860ea" } }
]);

$toString語法使用上,{ $toString: "要轉換的欄位" },而欄位名稱前面必須加上$符號。
$addFields語法使用上,{ $addFields: { 要新增的欄位名稱: 欄位值 } },如果該欄位名稱原本就已經存在,則會取代它。


第二個我在工作上採到的雷點是,日期時間資料格式不同的問題
有時存入的資料格式會是Date,EX: 2022–09–03T14:57:45.854Z
有時存入的資料格式會是Number,EX: 1662217065857(timestamp)

如果沒有轉換資料格式,基本上直接比對也會找不到資料
例如:資料庫的商品資料

{
  id: 1,
  name: "鍵盤",
  price: 4560,
  create_time: 2022-09-03T14:57:45.854Z // 時間等同於1662217065857(timestamp)
}

如果我們用這樣的的搜尋方式,基本上會回傳空陣列,因為無法正確比對兩種不同格式的時間

product.aggregate([
  { $match: { create_time: { $lte: 1662217065857 } } }
]);

必須將兩個資料型態,轉換成一樣的格式,例如以下的寫法

product.aggregate([
  { $addFields: { create_time: { $toLong: "$create_time" } } },
  { $match: { create_time: { $lte: 1662217065857 } } }
]);

其中$toLong可以將給定的資料,轉換成整數,詳細的轉換規則,可以參考官網上的這張表

本篇文章同步放在我的部落格,大家有空可以進來逛逛


上一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day4-用$match篩選資料
下一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day6-用$project新增欄位
系列文
被MongoDB用Aggregate暴打的後端小菜雞日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言