MongoDB 查詢欄位內容長度與數量統計

本篇文章將介紹如何查詢 MongoDB 字串欄位的長度以及數量。


人家說上戰場,直接面對需求是最佳的進步方式,雖然不會真的陣亡,但是在時間壓力下會進步神速。

某次遇到 issue 時,需要查詢現有的某個 collection 內,x 欄位字串長度超過 y 的資料筆數有多少。不看還好,一看也沒這麼單純,因此特別記錄一下。

目標 1: 查詢 x 欄位長度超過 20 的資料有哪些

這個思路很簡單,

  1. 使用 strLenCP 計算出長度
  2. 使用 gt / eq 找出符合長度的資料
  3. 最外層使用 expr 來做判斷表示式
1
2
3
db.getCollection('myctw').find({
"$expr": { "$gte": [ { "$strLenCP": "$apie.field-en" }, 30 ] }
})

上述就是查詢 myctw 這個 collection,apie.field-en 此欄位長度大於等於 30 的方式。

目標 2: 查詢目標 1 的總數量

看到目標 1 輕鬆達成,接下來我需要知道數量有多少,很自然地就在 .find() 最後加上 .count()

於是悲劇就發生了!

1
2
"errmsg" : "$strLenCP requires a string argument, found: missing",
"code" : 34471,

我百思不得其解,應該要可以的啊?
看了一下 errmsg 不是很理解,在網路上使用這個 code 去查詢也沒得到什麼結果,於是我先縮小範圍逐個擊破,嘗試過程就不贅述了,最後得到靈感的是我當初查詢的條件是子欄位,於是我換一個欄位查看看:

1
2
3
db.getCollection('myctw').find({
"$expr": { "$gte": [ { "$strLenCP": "$somefield" }, 30 ] }
}).count();

沒想到竟然成功了!後來確認這個錯誤的原因並不是子欄位,確實意思是:
要使用 $strLenCP 查詢,所有欄位必須是 string 且 存在
關鍵就在於後面的存在兩個字,只要有其中一筆資料不存在此欄位,就無法這樣查詢。

在這個時候我們不能忘記 Pipeline 的觀念,先過濾掉不存在此欄位的資料就沒沒問題囉!

1
2
3
4
db.getCollection('myctw').find({
"apie.field-en": {"$exists": true},
"$expr": { "$gte": [ { "$strLenCP": "$apie.field-en" }, 30 ] }
}).count();

搞定收工!

解法2 Regex

其實我還寫了一個透過 regex 來計算長度的方式,此方法雖然能略過不存在欄位進行計算,但是效能比較差,我不敢放到正式環境來使用。

1
2
3
db.getCollection('myctw').find({
"apie.field-en" : {$regex: /.{30,}/}
}).count();

解法3 Where

後來在網路上又看到更簡單的 $where 方式:

1
2
3
4
db.getCollection('myctw').find({
"apie.field-en": { $exists: true },
$where: "this.apie.field-en.length > 4"
}).count();

但一樣要記得加上 $exists 過濾。


最近忙於考試的準備,就花比較少時間在 blog 上,七月後繼續開工!!

  • 作者: MingYi Chou
  • 版權聲明: 轉載不用問,但請註明出處!本網誌均採用 BY-NC-SA 許可協議。