iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
自我挑戰組

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

被MongoDB用Aggregate暴打的後端小菜雞日記-day21-文字操作符

  • 分享至 

  • xImage
  •  

文字操作符其實有很多種類可以講,像是大小寫轉換、找特定字在文字中的位置、將字串合併等等,就讓我們一一做舉例。

首先假設我們有一些商品資料

  { id: 1, name: "USB", price: 1500, amount: 12 },
  { id: 2, name: "keyboard", price: 1200, amount: 12 },
  { id: 3, name: "mp3", price: 2100, amount: 12 }

如果我們要針對商品名稱,進行大小寫的轉換,這時候可以使用$toUpper$toLower這兩個操作符。

product.aggregate([
  {
    $project: {
      name_up: {
        $toUpper: "$name" // 商品名稱換成大寫
      },
      name_lower: {
        $toLower: "$name"  // 商品名稱換成小寫
      }
    }
  }
]);

// 最後回傳的資料
  { id: 1, name_up: "USB", name_lower: "usb" },
  { id: 2, name_up: "KEYBOARD", name_lower: "keyboard" },
  { id: 3, name_up: "MP3", name_lower: "mp3" }

這樣轉換有一個好處是,當我們再寫商品搜尋功能給顧客使用時,通常會自動幫顧客轉換大小寫,這樣容易使用關鍵字搜尋到更多的商品,實際寫法如下。

const key_word = "keyBoard";  // 顧客輸入的關鍵字
product.aggregate([
  {
    $addFields: {
      name: {
        $toLower: "$name" 
      }
    }
  },
  { $match: { name: key_word.toLowerCase() } } 
]);

// 最後回傳的資料
{ id: 2, name: "keyboard", price: 1600, amount: 12 }

ps.必須注意的是,除了商品名稱要換成小寫以外,關鍵字也要透過toLowerCase()(JS語法)轉換成小寫,這樣經過$match的比對才會是相同的。

另外提一下,其實有一個操作符$regexFind,可以讓使用者用正規表達搜尋文字資料,不過因為本人對正規表達式不太熟練,因此就不多做介紹了。


接下來用兩個文字,來示範如何用$concat將兩個文字合併再一起,以及使用$indexOfBytes找尋找特定字母,在文字中的位置。

db.collection.aggregate([
  {
    $addFields: {
      string_1: "cat",
      string_2: "dog"
    }
  },
  {
    $project: {
      // 把要合併的文字,寫入陣列內
      animal: { $concat: ["$string_1", "-", "$string_2"] },
      o_index: { $indexOfBytes: ["$string_2", "o"] }
    }
  }
]);

// 最後回傳的資料
{ _id: 1, animal: 'cat-dog', o_index: 1 },

其中$indexOfBytes的用法,跟之前在陣列操作符有介紹到的$indexOfArray很像,都是後面接一個陣列,依序帶入文字、搜尋的關鍵字、開始搜尋的位置、結束搜尋的位置,最後會傳一個數值,如果是-1代表搜尋不到,如果是其它數值,就代表是關鍵字所在的位置。


最後要來介紹一下$literal這個操作符,它的用途有點特別,可以讓特定字串不進行解析,避免文字中某些關鍵字被MongoDB當成指令或變數。

不曉得大家有沒有發現,MongoDB通常都會用$來區分是變數,還是一般的文字,這時候如果你剛好想寫金錢的符號$,後面接數字代表商品價格,如果沒有特別使用$literal,就有可能會出錯。

假設現在商品因為在美國販賣,所以以美金計價,資料如下(因為舉例方便都是賣56美金)

  { id: 1, name: "USB", price: "$56", amount: 12 }

如果我們想確認商品是不是賣56美金,可以用以下指令

product.aggregate([
  {
    $project: {
      // 錯誤寫法,因為讀取不到 56 這個欄位,所以不會和price欄位的值相等
      check_error: { $eq: ["$price", "$56"] }, 
      // 正確寫法,因為會把$56當成單純的字串來解讀
      check_success: { $eq: ["$price", { $literal: "$56" }] }
    }
  }
]);

// 最後回傳的資料
  { _id: 1,  check_error: false, check_success: true }

ps.如果對文字操作符有興趣的話,可以參考官方文件,有更詳細的說明

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


上一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day20-日期時間操作符(下)
下一篇
被MongoDB用Aggregate暴打的後端小菜雞日記-day22-那些年你不知道的Aggregate大小事
系列文
被MongoDB用Aggregate暴打的後端小菜雞日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言