【mongoDB查詢進階】聚合管道(三) -- 表達式操作符

回顧

相關文章回顧

mongoDB查詢進階--聚合管道(一)回顧
mongoDB查詢進階--聚合管道(二)回顧

管道操作符的分類

管道操作符可以分為三類:

  1. 階段操作符(Stage Operators)
  2. 表達式操作符(Expression Operators)--主要用于$project
  3. 累加器(Accumulators)--主要用于$group分組

參考MongoDB官網(wǎng):https://docs.mongodb.com/manual/reference/operator/aggregation

本篇主要內(nèi)容是管道操作符中的表達式操作符。

表達式操作符(Expression Operators)

表達式操作符主要用于在管道中構建表達式時使用弄企,使用類似于函數(shù)那樣需要參數(shù),主要用于$project操作符中,用于構建表達式,使用方法一般如下:

方法1:

{ <operator>: [ <argument1>, <argument2> ... ] }

方法2:

{ <operator>: <argument> }

表達式操作符分類

  • 布爾值操作符(Boolean Operators)
  • 集合操作符(Set Operators)
  • 比較操作符(Comparison Operators)
  • 數(shù)學操作符(Arithmetic Operators)
  • 字符串操作符(String Operators)
  • 文本搜索操作符(Text Search Operators)
  • 數(shù)組操作符(Array Operators)
  • 變量操作符(Variable Operators)
  • 字面量操作符(Literal Operators)
  • 日期操作符(Date Operators)
  • 條件操作符(Conditional Operators)
  • 數(shù)據(jù)類型操作符(Data Type Operators)

常用表達式操作符

  • 布爾值操作符(Boolean Operators)

操作符 簡述
$and 邏輯與操作符考余,當他的表達式中所有值都是true的時候,才返回true。 用法:{ $and: [ <expression1>, <expression2>, ... ] }蔽午。
$or 邏輯或操作符,當他的表達式中有值是true的時候酬蹋,就會返回true及老。用法:{ $or: [ <expression1>, <expression2>, ... ] }
$not 取反操作符,返回表達式中取反后的布爾值范抓。用法:{ $not: [ <expression> ] }
示例
例子 結果
{ $and: [ 1, "green" ] } true
{ $and: [ ] } true
{ $and: [ [ null ], [ false ], [ 0 ] ] } true
{ $and: [ null, true ] } false
{ $and: [ 0, true ] } false
{ $or: [ true, false ] } true
{ $or: [ [ false ], false ] } true
{ $or: [ null, 0, undefined ] } false
{ $or: [ ] } false
{ $not: [ true ] } false
{ $not: [ [ false ] ] } false
{ $not: [ false ] } true
{ $not: [ null ] } true
{ $not: [ 0 ] } true
  • 比較操作符(Comparison Operators)

操作符 簡述
$cmp 比較操作符骄恶,比較表達式中兩個值的大小,如果第一個值小于第二個值則返回-1匕垫,相等返回0僧鲁,大于返回1。用法{ $cmp: [ <expression1>, <expression2> ] }
$eq 比較表達式中兩個是否相等,是則返回true,否則返回false穷蛹。用法{ $eq: [ <expression1>, <expression2> ] }
$gt 比較表達式中第一個值是否大于第二個值,是則返回true春寿,否則返回false。用法{ $gt: [ <expression1>, <expression2> ] }
$gte 比較表達式中第一個值是否大于等于第二個值忽孽,是則返回true绑改,否則返回false。用法{ $gte: [ <expression1>, <expression2> ] }
$lt 比較表達式中第一個值是否小于第二個值兄一,是則返回true厘线,否則返回false。用法{ $lt: [ <expression1>, <expression2> ] }
$lte 比較表達式中第一個值是否小于等于第二個值瘾腰,是則返回true皆的,否則返回false。用法{ $lte: [ <expression1>, <expression2> ] }
$ne 比較表達式中兩個是否相等蹋盆,不過返回值與eq相反费薄,是則返回false,否則返回true栖雾。用法`{ne: [ <expression1>, <expression2> ] }`
示例

假設有一個關于考試成績的集合:

{ "_id" : 1, "name" : "abc1",  score: 80 }
{ "_id" : 2, "name" : "avc1",  score: 82 }
{ "_id" : 3, "name" : "adc1",  score: 79 }
{ "_id" : 4, "name" : "awc1",  score: 60 }
{ "_id" : 5, "name" : "xyz1",  score: 50 }
{ "_id" : 6, "name" : "VWZ1",  score: 100 }

操作如下:

db.collection.aggregate(
   [
     {
       $project:
          {
            name: 1,
            score: 1,
            cmp60: { $cmp: [ "$score", 60 ] },
            eq100: { $eq: [ "$score", 100 ] },
            gt80: { $gt: [ "$score", 80 ] },
            gte80: { $gte: [ "$score", 80 ] },
            lt80: { $lt: [ "$score", 80 ] },
            lte80: { $lte: [ "$score", 80 ] },
            ne100: { $ne: [ "$score", 100 ] },
            _id: 0
          }
     }
   ]
)

返回結果:

{ "name" : "abc1", score: 80, cmp60: 1, eq100: false, gt80: false, gte80: true, lt80: false, lte80: true, ne100: true }
{ "name" : "avc1", score: 82, cmp60: 1, eq100: false, gt80: true, gte80: true, lt80: false, lte80: false, ne100: true }
{ "name" : "adc1", score: 79, cmp60: 1, eq100: false, gt80: false, gte80: false, lt80: true, lte80: false, ne100: true }
{ "name" : "awc1", score: 60, cmp60: 0, eq100: false, gt80: false, gte80: false, lt80: true, lte80: true, ne100: true }
{ "name" : "xyz1", score: 50, cmp60: -1, eq100: false, gt80: false, gte80: false, lt80: true, lte80: true, ne100: true }
{ "name" : "VWZ1", score: 100, cmp60: 1, eq100: true, gt80: true, gte80: true, lt80: false, lte80: false, ne100: false }
  • 數(shù)學操作符(Arithmetic Operators)

操作符 簡述
$abs 求絕對值操作符楞抡,于v3.2版新加入。用法:{ $abs: <number> }
$add 求和操作符析藕,返回所有表達式相加起來的結果召廷。用法:{ $add: [ <expression1>, <expression2>, ... ] }
$ceil 進一法取整操作符,取 于v3.2版新加入。用法:{ $ceil: <number> }
$divide 求商操作符竞慢,返回表達式1除以表達式2的商先紫。用法:{ $divide: [ <expression1>, <expression2> ] }
$subtract 求差操作符,返回表達式1減去表達式2的結果筹煮。用法:{ $subtract: [ <expression1>, <expression2> ] }
$multiply 求積操作符遮精,返回所有表達式相乘的結果。用法:{ $multiply: [ <expression1>, <expression2>, ... ] }
$mod 求余操作符败潦,返回所有表達式1除以表達式2所得到的余數(shù)本冲。用法:{ $multiply: [ <expression1>, <expression2>] }
示例
例子 結果
{ $abs: -1 } 1
{ $abs: 1 } 1
{ $abs: null } null
{ $add: [1, 1] } 2
{ $ceil: 1 } 1
{ $ceil: 7.80 } 8
{ $ceil: -2.8 } -2
{ $divide: [40, 8] } 5
{ $subtract: [10, 8] } 2
{ $multiply: [5, 8] } 40
{ $mob: [80, 7] } 3
{ $mob: [80, 8] } 0

Tips: $add將一個日期類型和數(shù)字類型相加會變成日期類型。 這樣的話劫扒,當數(shù)據(jù)庫存儲的是時間戳但是需要又想對其使用日期操作符的話檬洞,就可以通過這樣的方法,先讓其變成日期類型沟饥,然后再使用日期操作符添怔,用法參考:{ $add: [ new Date(0), '$ts' ] }

  • 字符串操作符(String Operators)

操作符 簡述
$concat 連接操作符闷板,將給定表達式中的字符串連接一起澎灸。用法:{ $concat: [ <expression1>, <expression2>, ... ] }
$split 切割操作符院塞,用于對字符串進行分切遮晚。用法:{ $split: [ <string expression>, <delimiter> ] }
$toLower 用于返回字符串的小寫形式。用法:{ $toLower: <expression> }
$toUpper 用于返回字符串的大寫形式拦止。用法:{ $toUpper: <expression> }
$substr 用于返回子字符串县遣,v3.4+版本不建議使用,應該使用substrBytes或substrCP汹族,v3.4+版本使用的話萧求,相當于substrBytes。用法:{ $substr: [ <string>, <start>, <length> ] }
$substrBytes 用于根據(jù)UTF-8下的字節(jié)位置返回子字符串(起始位置為0)顶瞒,于v3.4新增夸政。用法:{ $substrBytes: [ <string expression>, <byte index>, <byte count> ] }
$substrCP 用于根據(jù)UTF-8下的Code Point位置返回子字符串(起始位置為0),于v3.4新增榴徐。用法:{ $substrCP: [ <string expression>, <code point index>, <code point count> ] }

Code Point: (1) Any value in the Unicode codespace; that is, the range of integers from 0 to 10FFFF16. Not all code points are assigned to encoded characters. See code point type. (2) A value, or position, for a character, in any coded character set.

示例
例子 結果
{ $concat: [ "item", " - ", "a" ] } item - a
{ $split: [ "June-15-2013", "-" ] } [ "June", "15", "2013" ]
{ $split: [ "banana split", "a" ] } [ "b", "n", "n", " split" ]
{ $split: [ "headphone jack", 7 ] } $split第二個參數(shù)必須是一個字符串守问,不能是數(shù)字
{ $toLower: "ITEM" } "item"
{ $toLower: "Item" } "item"
{ $toLower: null } ""
{ $toUpper: "item" } "ITEM"
{ $toUpper: "Item" } "ITEM"
{ $toUpper: null } ""
{ $substrBytes: [ "abcde", 1, 2 ] } "bc"
{ $substrBytes: [ "Hello World!", 6, 5 ] } "World"
{ $substrBytes: [ "cafétéria", 0, 5 ] } "café"
{ $substrBytes: [ "cafétéria", 5, 4 ] } "tér"
{ $substrBytes: [ "cafétéria", 7, 3 ] } "Error: Invalid range, starting index is a UTF-8 continuation byte."
{ $substrBytes: [ "cafétéria", 3, 1 ] } "Error: Invalid range, ending index is in the middle of a UTF-8 character."
{ $substrBytes: [ "壽司sushi", 0, 3 ] } "壽"
{ $substrCP: [ "abcde", 1, 2 ] } "bc"
{ $substrCP: [ "Hello World!", 6, 5 ] } "World"
{ $substrCP: [ "cafétéria", 0, 5 ] } "cafét"
{ $substrCP: [ "cafétéria", 5, 4 ] } "tér"
{ $substrCP: [ "cafétéria", 7, 3 ] } "ia"
{ $substrCP: [ "cafétéria", 3, 1 ] } "é"
{ $substrCP: [ "壽司sushi", 0, 3 ] } "壽司s"
  • 日期操作符(Date Operators)

操作符 簡述
$dayOfYear 返回一年中的一天,值在1和366(閏年)之間坑资。用法:{ $dayOfYear: <expression> }
$dayOfMonth 返回一個月中的一天耗帕,值在1和31之間。用法:{ $dayOfMonth: <expression> }
$dayOfWeek 返回一周中的一天袱贮,值在1(周日)和7(周六)之間仿便。用法:{ $dayOfWeek: <expression> }
$year 返回年份,eg:2017嗽仪。用法:{ $year: <expression> }
$month 返回月份荒勇,值在1和12之間搀擂。用法:{ $month: <expression> }
$week 返回周 威恼,值在0和53之間斤蔓。用法:{ $week: <expression> }
$hour 返回時 ,值在0和23之間走越。用法:{ $hour: <expression> }
$minute 返回分 ,值在0和59之間低淡。用法:{ $minute: <expression> }
$second 返回秒,值在0和60之間(閏秒)戒傻。用法:{ $second: <expression> }
$millisecond 返回毫秒不翩,值在0和999之間灭必。用法:{ $millisecond: <expression> }
$dateToString 返回日期的字符串播歼。用法:{ $dateToString: { format: <formatString>, date: <dateExpression> } }
示例

假如有以下數(shù)據(jù):

{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:15:39.736Z") }

進行如下操作:

db.collection.aggregate(
   [
     {
       $project:
         {
           year: { $year: "$date" },
           month: { $month: "$date" },
           day: { $dayOfMonth: "$date" },
           hour: { $hour: "$date" },
           minutes: { $minute: "$date" },
           seconds: { $second: "$date" },
           milliseconds: { $millisecond: "$date" },
           dayOfYear: { $dayOfYear: "$date" },
           dayOfWeek: { $dayOfWeek: "$date" },
           week: { $week: "$date" },
           yearMonthDayUTC: { $dateToString: { format: "%Y-%m-%d", date: "$date" } },
          time: { $dateToString: { format: "%H:%M:%S:%L", date: "$date" } }
         }
     }
   ]
)

返回結果:

{
  "_id" : 1,
  "year" : 2014,
  "month" : 1,
  "day" : 1,
  "hour" : 8,
  "minutes" : 15,
  "seconds" : 39,
  "milliseconds" : 736,
  "dayOfYear" : 1,
  "dayOfWeek" : 4,
  "week" : 0,
  "yearMonthDayUTC" : "2014-01-01", 
  "time" : "08:15:39:736"
}
  • 條件操作符(Conditional Operators)

操作符 簡述
$cond 用法:{ $cond: [ <boolean-expression>, <true-case>, <false-case> ] } 或者 v2.6+還支持{ $cond: { if: <boolean-expression>, then: <true-case>, else: <false-case-> } }
$ifNull 用法:{ $ifNull: [ <expression>, <replacement-expression-if-null> ] }
示例

假設有一個關于考試成績的集合:

{ "_id" : 1, "name" : "a",  score: 80 }
{ "_id" : 2, "name" : "b",  score: 69 }
{ "_id" : 3, "name" : "c",  score: 53 }
{ "_id" : 3, "name" : null,  score: 70 }

操作如下:

db.collection.aggregate(
   [
      {
         $project:
           {
              _id: 0,
              score: 1,
              pass:
                {
                  $cond: [ { $gte: [ "$score", 60 ] }, 1, 0 ]
                },
              description: { $ifNull: [ "$name", "Unspecified" ] } 
           }
      }
   ]
)

返回結果:

{ "name" : "a",  score: 80, pass: 1 }
{ "name" : "b",  score: 69, pass: 1 }
{ "name" : "c",  score: 53, pass: 0 }
{ "name" : "Unspecified",  score: 70, pass: 1 }

總結

本文介紹表達式操作符的分類和常用的表達式操作符的用法刊橘,表達式操作符主要作用于$project下败晴,通過使用這些操作符可以對文檔中的字面量進行處理并返回位衩,進而返回更多有用的數(shù)據(jù)。

感謝閱讀~

如果想了解更多技術圈內(nèi)容和技術分享,可以搜索【今天不想寫代碼】或者掃描以下二維碼關注公眾號:

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市裳食,隨后出現(xiàn)的幾起案子矛市,更是在濱河造成了極大的恐慌,老刑警劉巖诲祸,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浊吏,死亡現(xiàn)場離奇詭異憨愉,居然都是意外死亡,警方通過查閱死者的電腦和手機卿捎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門配紫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人午阵,你說我怎么就攤上這事躺孝。” “怎么了底桂?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵植袍,是天一觀的道長。 經(jīng)常有香客問我籽懦,道長于个,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任暮顺,我火速辦了婚禮厅篓,結果婚禮上,老公的妹妹穿的比我還像新娘捶码。我一直安慰自己羽氮,他們只是感情好,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布惫恼。 她就那樣靜靜地躺著档押,像睡著了一般。 火紅的嫁衣襯著肌膚如雪祈纯。 梳的紋絲不亂的頭發(fā)上令宿,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音腕窥,去河邊找鬼粒没。 笑死,一個胖子當著我的面吹牛油昂,可吹牛的內(nèi)容都是我干的革娄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冕碟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了匆浙?” 一聲冷哼從身側響起安寺,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎首尼,沒想到半個月后挑庶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體言秸,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年迎捺,在試婚紗的時候發(fā)現(xiàn)自己被綠了举畸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡凳枝,死狀恐怖抄沮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情岖瑰,我是刑警寧澤叛买,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站蹋订,受9級特大地震影響率挣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜露戒,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一椒功、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧智什,春花似錦蛾茉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至节沦,卻和暖如春键思,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背甫贯。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工吼鳞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叫搁。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓赔桌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親渴逻。 傳聞我的和親對象是個殘疾皇子疾党,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容