天天看點

【mongoDB查詢進階】聚合管道(三)--表達式操作符https://segmentfault.com/a/1190000010910985表達式操作符(Expression Operators)總結

https://segmentfault.com/a/1190000010910985

管道操作符的分類

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

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

表達式操作符(Expression Operators)

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

方法1:

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

方法2:

{ <operator>: <argument> }      

表達式操作符分類

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

常用表達式操作符

操作符 簡述
$and 邏輯與操作符,當他的表達式中所有值都是true的時候,才傳回true。 用法:

{ $and: [ <expression1>, <expression2>, ... ] }

$or 邏輯或操作符,當他的表達式中有值是true的時候,就會傳回true。用法:

{ $or: [ <expression1>, <expression2>, ... ] }

$not 取反操作符,傳回表達式中取反後的布爾值。用法:

{ $not: [ <expression> ] }

示例
例子 結果

{ $and: [ 1, "green" ] }

true

{ $and: [ ] }

{ $and: [ [ null ], [ false ], [ 0 ] ] }

{ $and: [ null, true ] }

false

{ $and: [ 0, true ] }

{ $or: [ true, false ] }

{ $or: [ [ false ], false ] }

{ $or: [ null, 0, undefined ] }

{ $or: [ ] }

{ $not: [ true ] }

{ $not: [ [ false ] ] }

{ $not: [ false ] }

{ $not: [ null ] }

{ $not: [ 0 ] }

$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 }      
$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所得到的餘數。用法:

{ $multiply: [ <expression1>, <expression2>] }

{ $abs: -1 }

1

{ $abs: 1 }

{ $abs: null }

null

{ $add: [1, 1] }

2

{ $ceil: 1 }

{ $ceil: 7.80 }

8

{ $ceil: -2.8 }

-2

{ $divide: [40, 8] }

5

{ $subtract: [10, 8] }

{ $multiply: [5, 8] }

40

{ $mob: [80, 7] }

3

{ $mob: [80, 8] }

Tips: 

$add

将一個日期類型和數字類型相加會變成日期類型。 這樣的話,當資料庫存儲的是時間戳但是需要又想對其使用日期操作符的話,就可以通過這樣的方法,先讓其變成日期類型,然後再使用日期操作符,用法參考:

{ $add: [ new Date(0), '$ts' ] }

$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 用于根據UTF-8下的位元組位置傳回子字元串(起始位置為0),于v3.4新增。用法:

{ $substrBytes: [ <string expression>, <byte index>, <byte count> ] }

$substrCP 用于根據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第二個參數必須是一個字元串,不能是數字

{ $toLower: "ITEM" }

"item"

{ $toLower: "Item" }

{ $toLower: null }

""

{ $toUpper: "item" }

"ITEM"

{ $toUpper: "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 ] }

{ $substrCP: [ "Hello World!", 6, 5 ] }

{ $substrCP: [ "cafétéria", 0, 5 ] }

"cafét"

{ $substrCP: [ "cafétéria", 5, 4 ] }

{ $substrCP: [ "cafétéria", 7, 3 ] }

"ia"

{ $substrCP: [ "cafétéria", 3, 1 ] }

"é"

{ $substrCP: [ "壽司sushi", 0, 3 ] }

"壽司s"
$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> } }

假如有以下資料:

{ "_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"
}      
$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下,通過使用這些操作符可以對文檔中的字面量進行處理并傳回,進而傳回更多有用的資料。