mongodb的聚合管道

我们先介绍一下 MongoDB 的聚合功能,聚合操作主要用于对数据的批量处理,往往将记录按条件分组以后,然后再进行一系列操作,例如,求最大值、最小值、平均值,求和等操作。聚合操作还能够对记录进行复杂的操作,主要用于数理统计和数据挖掘。在 MongoDB 中,聚合操作的输入是集合中的文档,输出可以是一个文档,也可以是多条文档。在管道查询过程中,上次查询的结果可以为这次查询的条件。

使用阶段操作符之前,我们先看一下 article 集合中的文档列表,也就是范例中用到的数据。

>db.article.find().pretty()

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7570")

   "title": "MongoDB Aggregate",

   "author": "liruihuan",

   "tags": ['Mongodb', 'Database', 'Query'],

   "pages": 5,

   "time": ISODate("2017-04-09T11:42:39.736Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7571")

   "title": "MongoDB Index",

   "author": "liruihuan",

   "tags": ['Mongodb', 'Index', 'Query'],

   "pages": 3,

   "time": ISODate("2017-04-09T11:43:39.236Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7572")

   "title": "MongoDB Query",

   "author": "eryueyang",

   "tags": ['Mongodb', 'Query'],

   "pages": 8,

   "time": ISODate("2017-04-09T11:44:56.276Z")

}

1.1.1、$project 

作用

修改文档的结构,可以用来重命名、增加或删除文档中的字段。

范例1

只返回文档中 title 和 author 字段

.article.aggregate([{$project:{_id:0, title:1, author:1 }}])

{ "title": "MongoDB Aggregate",  "author": "liruihuan"},

{ "title": "MongoDB Index",  "author": "liruihuan"},

{ "title": "MongoDB Query",  "author": "eryueyang"}

因为字段 _id 是默认显示的,这里必须用 _id:0 把字段_id过滤掉。

范例2

把文档中 pages 字段的值都增加10。并重命名成 newPages 字段。


>db.article.aggregate(

   [

      {

          $project:{

               _id:0,

               title:1,

               author:1,

               newPages: {$add:["$Pages",10]}

         }

      }

   ]

)

{ "title": "MongoDB Aggregate",  "author": "liruihuan", "newPages": 15 },

{ "title": "MongoDB Index",  "author": "liruihuan", "newPages": 13  },

{ "title": "MongoDB Query",  "author": "eryueyang", "newPages": 18  }

其中,$add 是 加 的意思,是算术类型表达式操作符,具体表达式操作符,下面会讲到。

1.1.2、$match

作用

用于过滤文档。用法类似于 find() 方法中的参数。

范例

查询出文档中 pages 字段的值大于等于5的数据。

.article.aggregate(

    [

         {

              $match: {"pages": {$gte: 5}}

         }

    ]

   ).pretty()

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7570")

   "title": "MongoDB Aggregate",

   "author": "liruihuan",

   "tags": ['Mongodb', 'Database', 'Query'],

   "pages": 5,

   "time": ISODate("2017-04-09T11:42:39.736Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7572")

   "title": "MongoDB Query",

   "author": "eryueyang",

   "tags": ['Mongodb', 'Query'],

   "pages": 8,

   "time": ISODate("2017-04-09T11:44:56.276Z")

}

注:

在 $match 中不能使用 $where 表达式操作符

如果 $match 位于管道的第一个阶段,可以利用索引来提高查询效率

$match 中使用 $text 操作符的话,只能位于管道的第一阶段

$match 尽量出现在管道的最前面,过滤出需要的数据,在后续的阶段中可以提高效率。

1.1.3、$group

作用

将集合中的文档进行分组,可用于统计结果。

范例

从 article 中得到每个 author 的文章数,并输入 author 和对应的文章数。


>db.article.aggregate(

    [

         {

              $group: {_id: "$author", total: {$sum: 1}}

         }

    ]

   )

{"_id": "eryueyang", "total": 1}

{"_id": "liruihuan", "total": 2}

1.1.4、$sort

作用

将集合中的文档进行排序。

范例

让集合 article 以 pages 升序排列

>db.article.aggregate([{$sort: {"pages": 1}}]).pretty()

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7571")

   "title": "MongoDB Index",

   "author": "liruihuan",

   "tags": ['Mongodb', 'Index', 'Query'],

   "pages": 3,

   "time": ISODate("2017-04-09T11:43:39.236Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7570")

   "title": "MongoDB Aggregate",

   "author": "liruihuan",

   "tags": ['Mongodb', 'Database', 'Query'],

   "pages": 5,

   "time": ISODate("2017-04-09T11:42:39.736Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7572")

   "title": "MongoDB Query",

   "author": "eryueyang",

   "tags": ['Mongodb', 'Query'],

   "pages": 8,

   "time": ISODate("2017-04-09T11:44:56.276Z")

}

  如果以降序排列,则设置成 "pages": -1

1.1.5、$limit

作用

限制返回的文档数量

范例

返回集合 article 中前两条文档

>db.article.aggregate([{$limit: 2}]).pretty()

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7570")

   "title": "MongoDB Aggregate",

   "author": "liruihuan",

   "tags": ['Mongodb', 'Database', 'Query'],

   "pages": 5,

   "time": ISODate("2017-04-09T11:42:39.736Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7571")

   "title": "MongoDB Index",

   "author": "liruihuan",

   "tags": ['Mongodb', 'Index', 'Query'],

   "pages": 3,

   "time": ISODate("2017-04-09T11:43:39.236Z")

}

1.1.6、$skip

作用

跳过指定数量的文档,并返回余下的文档。

范例

跳过集合 article 中一条文档,输出剩下的文档

rticle.aggregate([{$skip: 1}]).pretty()

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7571")

   "title": "MongoDB Index",

   "author": "liruihuan",

   "tags": ['Mongodb', 'Index', 'Query'],

   "pages": 3,

   "time": ISODate("2017-04-09T11:43:39.236Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7572")

   "title": "MongoDB Query",

   "author": "eryueyang",

   "tags": ['Mongodb', 'Query'],

   "pages": 8,

   "time": ISODate("2017-04-09T11:44:56.276Z")

}

1.1.7、$unwind

作用

将文档中数组类型的字段拆分成多条,每条文档包含数组中的一个值。

范例

把集合 article 中 title="MongoDB Aggregate" 的 tags 字段拆分


db.article.aggregate(

    [

         {

              $match: {"title": "MongoDB Aggregate"}

         },

         {

              $unwind: "$tags"

         }

    ]

   ).pretty()

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7570")

   "title": "MongoDB Aggregate",

   "author": "liruihuan",

   "tags": "Mongodb",

   "pages": 5,

   "time": ISODate("2017-04-09T11:42:39.736Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7570")

   "title": "MongoDB Aggregate",

   "author": "liruihuan",

   "tags": "Database",

   "pages": 5,

   "time": ISODate("2017-04-09T11:42:39.736Z")

},

{

   "_id": ObjectId("58e1d2f0bb1bbc3245fa7570")

   "title": "MongoDB Aggregate",

   "author": "liruihuan",

   "tags": "Query",

   "pages": 5,

   "time": ISODate("2017-04-09T11:42:39.736Z")

}

注:

$unwind 参数数组字段为空或不存在时,待处理的文档将会被忽略,该文档将不会有任何输出

$unwind 参数不是一个数组类型时,将会抛出异常

$unwind 所作的修改,只用于输出,不能改变原文档

1.2、表达式操作符

 表达式操作符有很多操作类型,其中最常用的有布尔管道聚合操作、集合操作、比较聚合操作、算术聚合操作、字符串聚合操作、数组聚合操作、日期聚合操作、条件聚合操作、数据类型聚合操作等。每种类型都有很多用法,这里就不一一举例了。

1.2.1、布尔管道聚合操作(Boolean Aggregation Operators)

名称说明

$andReturnstrueonly whenallits expressions evaluate totrue. Accepts any number of argument expressions.

$orReturnstruewhenanyof its expressions evaluates totrue. Accepts any number of argument expressions.

$notReturns the boolean value that is the opposite of its argument expression. Accepts a single argument expression.

范例

假如有一个集合 mycol

{ "_id": 1, "item": "abc1", description: "product 1", qty: 300 }

{ "_id": 2, "item": "abc2", description: "product 2", qty: 200 }

{ "_id": 3, "item": "xyz1", description: "product 3", qty: 250 }

{ "_id": 4, "item": "VWZ1", description: "product 4", qty: 300 }

{ "_id": 5, "item": "VWZ2", description: "product 5", qty: 180 }

确定 qty 是否大于250或者小于200

db.mycol.aggregate(

   [

     {

       $project:

          {

            item: 1,

            result: { $or: [ { $gt: [ "$qty", 250 ] }, { $lt: [ "$qty", 200 ] } ] }

          }

     }

   ]

)

{ "_id": 1, "item": "abc1", "result": true}

{ "_id": 2, "item": "abc2", "result": false}

{ "_id": 3, "item": "xyz1", "result": false}

{ "_id": 4, "item": "VWZ1", "result": true}

{ "_id": 5, "item": "VWZ2", "result": true}

1.2.2、集合操作(Set Operators)

用于集合操作,求集合的并集、交集、差集运算。

名称说明

$setEqualsReturnstrueif the input sets have the same distinct elements. Accepts two or more argument expressions.

$setIntersectionReturns a set with elements that appear inallof the input sets. Accepts any number of argument expressions.

$setUnionReturns a set with elements that appear inanyof the input sets. Accepts any number of argument expressions.

$setDifferenceReturns a set with elements that appear in the first set but not in the second set; i.e. performs a relative complement of the second set relative to the first. Accepts exactly two argument expressions.

$setIsSubsetReturnstrueif all elements of the first set appear in the second set, including when the first set equals the second set; i.e. not a strict subset. Accepts exactly two argument expressions.

$anyElementTrueReturnstrueifanyelements of a set evaluate totrue; otherwise, returnsfalse. Accepts a single argument expression.

$allElementsTrueReturnstrueifnoelement of a set evaluates tofalse, otherwise, returnsfalse. Accepts a single argument expression.

范例

假如有一个集合 mycol

{ "_id": 1, "A": [ "red", "blue"], "B": [ "red", "blue"] }

{ "_id": 2, "A": [ "red", "blue"], "B": [ "blue", "red", "blue"] }

{ "_id": 3, "A": [ "red", "blue"], "B": [ "red", "blue", "green"] }

{ "_id": 4, "A": [ "red", "blue"], "B": [ "green", "red"] }

{ "_id": 5, "A": [ "red", "blue"], "B": [ ] }

{ "_id": 6, "A": [ "red", "blue"], "B": [ [ "red"], [ "blue"] ] }

{ "_id": 7, "A": [ "red", "blue"], "B": [ [ "red", "blue"] ] }

{ "_id": 8, "A": [ ], "B": [ ] }

{ "_id": 9, "A": [ ], "B": [ "red"] }

求出集合 mycol 中 A 和 B 的交集

db.mycol.aggregate(

   [

     { $project: { A:1, B: 1, allValues: { $setUnion: [ "$A", "$B"] }, _id: 0 } }

   ]

)

{ "A": [ "red", "blue"], "B": [ "red", "blue"], "allValues": [ "blue", "red"] }

{ "A": [ "red", "blue"], "B": [ "blue", "red", "blue"], "allValues": [ "blue", "red"] }

{ "A": [ "red", "blue"], "B": [ "red", "blue", "green"], "allValues": [ "blue", "red", "green"] }

{ "A": [ "red", "blue"], "B": [ "green", "red"], "allValues": [ "blue", "red", "green"] }

{ "A": [ "red", "blue"], "B": [ ], "allValues": [ "blue", "red"] }

{ "A": [ "red", "blue"], "B": [ [ "red"], [ "blue"] ], "allValues": [ "blue", "red", [ "red"], [ "blue"] ] }

{ "A": [ "red", "blue"], "B": [ [ "red", "blue"] ], "allValues": [ "blue", "red", [ "red", "blue"] ] }

{ "A": [ ], "B": [ ], "allValues": [ ] }

{ "A": [ ], "B": [ "red"], "allValues": [ "red"] }

1.2.3、比较聚合操作(Comparison Aggregation Operators)

名称说明

$cmpReturns:0if the two values are equivalent,1if the first value is greater than the second, and-1if the first value is less than the second.

$eqReturnstrueif the values are equivalent.

$gtReturnstrueif the first value is greater than the second.

$gteReturnstrueif the first value is greater than or equal to the second.

$ltReturnstrueif the first value is less than the second.

$lteReturnstrueif the first value is less than or equal to the second.

$neReturnstrueif the values arenotequivalent.

这里就不举例了,之前的例子有用到过。

1.2.4、算术聚合操作(Arithmetic Aggregation Operators)

名称说明

$absReturns the absolute value of a number.

$addAdds numbers to return the sum, or adds numbers and a date to return a new date. If adding numbers and a date, treats the numbers as milliseconds. Accepts any number of argument expressions, but at most, one expression can resolve to a date.

$ceilReturns the smallest integer greater than or equal to the specified number.

$divideReturns the result of dividing the first number by the second. Accepts two argument expressions.

$expRaiseseto the specified exponent.

$floorReturns the largest integer less than or equal to the specified number.

$lnCalculates the natural log of a number.

$logCalculates the log of a number in the specified base.

$log10Calculates the log base 10 of a number.

$modReturns the remainder of the first number divided by the second. Accepts two argument expressions.

$multiplyMultiplies numbers to return the product. Accepts any number of argument expressions.

$powRaises a number to the specified exponent.

$sqrtCalculates the square root.

$subtractReturns the result of subtracting the second value from the first. If the two values are numbers, return the difference. If the two values are dates, return the difference in milliseconds. If the two values are a date and a number in milliseconds, return the resulting date. Accepts two argument expressions. If the two values are a date and a number, specify the date argument first as it is not meaningful to subtract a date from a number.

$truncTruncates a number to its integer.

范例

假如有一个集合 mycol

{ _id: 1, start: 5, end: 8 }

{ _id: 2, start: 4, end: 4 }

{ _id: 3, start: 9, end: 7 }

{ _id: 4, start: 6, end: 7 }

求集合 mycol 中 start 减去 end 的绝对值

db.mycol.aggregate([

   {

     $project: { delta: { $abs: { $subtract: [ "$start", "$end"] } } }

   }

])

{ "_id": 1, "delta": 3 }

{ "_id": 2, "delta": 0 }

{ "_id": 3, "delta": 2 }

{ "_id": 4, "delta": 1 }

1.2.5、字符串聚合操作(String Aggregation Operators)

名称说明

$concatConcatenates any number of strings.

$indexOfBytesSearches a string for an occurence of a substring and returns the UTF-8 byte index of the first occurence. If the substring is not found, returns-1.

$indexOfCPSearches a string for an occurence of a substring and returns the UTF-8 code point index of the first occurence. If the substring is not found, returns-1.

$splitSplits a string into substrings based on a delimiter. Returns an array of substrings. If the delimiter is not found within the string, returns an array containing the original string.

$strLenBytesReturns the number of UTF-8 encoded bytes in a string.

$strLenCPReturns the number of UTF-8 code points in a string.

$strcasecmpPerforms case-insensitive string comparison and returns:0if two strings are equivalent,1if the first string is greater than the second, and-1if the first string is less than the second.

$substrDeprecated. Use$substrBytesor$substrCP.

$substrBytesReturns the substring of a string. Starts with the character at the specified UTF-8 byte index (zero-based) in the string and continues for the specified number of bytes.

$substrCPReturns the substring of a string. Starts with the character at the specified UTF-8 code point (CP) index (zero-based) in the string and continues for the number of code points specified.

$toLowerConverts a string to lowercase. Accepts a single argument expression.

$toUpperConverts a string to uppercase. Accepts a single argument expression.

范例

假如有一个集合 mycol

{ "_id": 1, "city": "Berkeley, CA", "qty": 648 }

{ "_id": 2, "city": "Bend, OR", "qty": 491 }

{ "_id": 3, "city": "Kensington, CA", "qty": 233 }

{ "_id": 4, "city": "Eugene, OR", "qty": 842 }

{ "_id": 5, "city": "Reno, NV", "qty": 655 }

{ "_id": 6, "city": "Portland, OR", "qty": 408 }

{ "_id": 7, "city": "Sacramento, CA", "qty": 574 }

以 ',' 分割集合 mycol 中字符串city的值,用 $unwind 拆分成多个文档,匹配出城市名称只有两个字母的城市,并求和各个城市中 qty 的值,最后以降序排序。

db.mycol.aggregate([

  { $project : { city_state : { $split: ["$city", ", "] }, qty : 1 } },

  { $unwind : "$city_state"},

  { $match : { city_state : /[A-Z]{2}/ } },

  { $group: { _id: { "state": "$city_state"}, total_qty : { "$sum": "$qty"} } },

  { $sort : { total_qty : -1 } }

])

{ "_id": { "state": "OR"}, "total_qty": 1741 }

{ "_id": { "state": "CA"}, "total_qty": 1455 }

{ "_id": { "state": "NV"}, "total_qty": 655 }

1.2.6、数组聚合操作(Array Aggregation Operators)

名称说明

$arrayElemAtReturns the element at the specified array index.

$concatArraysConcatenates arrays to return the concatenated array.

$filterSelects a subset of the array to return an array with only the elements that match the filter condition.

$indexOfArraySearches an array for an occurence of a specified value and returns the array index of the first occurence. If the substring is not found, returns-1.

$isArrayDetermines if the operand is an array. Returns a boolean.

$rangeOutputs an array containing a sequence of integers according to user-defined inputs.

$reverseArrayReturns an array with the elements in reverse order.

$reduceApplies an expression to each element in an array and combines them into a single value.

$sizeReturns the number of elements in the array. Accepts a single expression as argument.

$sliceReturns a subset of an array.

$zipMerge two lists together.

$inReturns a boolean indicating whether a specified value is in an array.

范例

假如有一个集合 mycol


{ "_id": 1, "name": "dave123", favorites: [ "chocolate", "cake", "butter", "apples"] }

{ "_id": 2, "name": "li", favorites: [ "apples", "pudding", "pie"] }

{ "_id": 3, "name": "ahn", favorites: [ "pears", "pecans", "chocolate", "cherries"] }

{ "_id": 4, "name": "ty", favorites: [ "ice cream"] }

求出集合 mycol 中 favorites 的第一项和最后一项


db.mycol.aggregate([

   {

     $project:

      {

         name: 1,

         first: { $arrayElemAt: [ "$favorites", 0 ] },

         last: { $arrayElemAt: [ "$favorites", -1 ] }

      }

   }

])

{ "_id": 1, "name": "dave123", "first": "chocolate", "last": "apples"}

{ "_id": 2, "name": "li", "first": "apples", "last": "pie"}

{ "_id": 3, "name": "ahn", "first": "pears", "last": "cherries"}

{ "_id": 4, "name": "ty", "first": "ice cream", "last": "ice cream"}

1.2.7、日期聚合操作(Date Aggregation Operators)

名称说明

$dayOfYearReturns the day of the year for a date as a number between 1 and 366 (leap year).

$dayOfMonthReturns the day of the month for a date as a number between 1 and 31.

$dayOfWeekReturns the day of the week for a date as a number between 1 (Sunday) and 7 (Saturday).

$yearReturns the year for a date as a number (e.g. 2014).

$monthReturns the month for a date as a number between 1 (January) and 12 (December).

$weekReturns the week number for a date as a number between 0 (the partial week that precedes the first Sunday of the year) and 53 (leap year).

$hourReturns the hour for a date as a number between 0 and 23.

$minuteReturns the minute for a date as a number between 0 and 59.

$secondReturns the seconds for a date as a number between 0 and 60 (leap seconds).

$millisecondReturns the milliseconds of a date as a number between 0 and 999.

$dateToStringReturns the date as a formatted string.

$isoDayOfWeekReturns the weekday number in ISO 8601 format, ranging from1(for Monday) to7(for Sunday).

$isoWeekReturns the week number in ISO 8601 format, ranging from1to53. Week numbers start at1with the week (Monday through Sunday) that contains the year’s first Thursday.

$isoWeekYearReturns the year number in ISO 8601 format. The year starts with the Monday of week 1 (ISO 8601) and ends with the Sunday of the last week (ISO 8601).

范例

假如有一个集合 mycol

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

得到集合 mycol 中 date 字段的相关日期值


db.mycol.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"}

         }

     }

   ]

)

{

  "_id": 1,

  "year": 2017,

  "month": 1,

  "day": 1,

  "hour": 8,

  "minutes": 15,

  "seconds": 39,

  "milliseconds": 736,

  "dayOfYear": 1,

  "dayOfWeek": 1,

  "week": 0

}

1.2.8、条件聚合操作(Conditional Aggregation Operators)

名称说明

$condA ternary operator that evaluates one expression, and depending on the result, returns the value of one of the other two expressions. Accepts either three expressions in an ordered list or three named parameters.

$ifNullReturns either the non-null result of the first expression or the result of the second expression if the first expression results in a null result. Null result encompasses instances of undefined values or missing fields. Accepts two expressions as arguments. The result of the second expression can be null.

$switchEvaluates a series of case expressions. When it finds an expression which evaluates totrue,$switchexecutes a specified expression and breaks out of the control flow.

范例

假如有一个集合 mycol


{ "_id": 1, "item": "abc1", qty: 300 }

{ "_id": 2, "item": "abc2", qty: 200 }

{ "_id": 3, "item": "xyz1", qty: 250 }

如果集合 mycol 中 qty 字段值大于等于250,则返回30,否则返回20


db.mycol.aggregate(

   [

      {

         $project:

           {

             item: 1,

             discount:

               {

                 $cond: { if: { $gte: [ "$qty", 250 ] }, then: 30, else: 20 }

               }

           }

      }

   ]

)

{ "_id": 1, "item": "abc1", "discount": 30 }

{ "_id": 2, "item": "abc2", "discount": 20 }

{ "_id": 3, "item": "xyz1", "discount": 30 }

1.2.9、数据类型聚合操作(Data Type Aggregation Operators)

名称说明

$typeReturn the BSON data type of the field.

范例

假如有一个集合 mycol


{ _id: 0, a : 8 }

{ _id: 1, a : [ 41.63, 88.19 ] }

{ _id: 2, a : { a : "apple", b : "banana", c: "carrot"} }

{ _id: 3, a :  "caribou"}

{ _id: 4, a : NumberLong(71) }

{ _id: 5 }

获取文档中 a 字段的数据类型

db.mycol.aggregate([{

    $project: {

       a : { $type: "$a"}

    }

}])

{ _id: 0, "a": "double"}

{ _id: 1, "a": "array"}

{ _id: 2, "a": "object"}

{ _id: 3, "a": "string"}

{ _id: 4, "a": "long"}

{ _id: 5, "a": "missing"}

1.3、聚合管道优化

默认情况下,整个集合作为聚合管道的输入,为了提高处理数据的效率,可以使用一下策略:

将 $match 和 $sort 放到管道的前面,可以给集合建立索引,来提高处理数据的效率。

可以用 $match、$limit、$skip 对文档进行提前过滤,以减少后续处理文档的数量。

当聚合管道执行命令时,MongoDB 也会对各个阶段自动进行优化,主要包括以下几个情况:

$sort + $match 顺序优化

如果 $match 出现在 $sort 之后,优化器会自动把 $match 放到 $sort 前面

2. $skip + $limit 顺序优化

如果 $skip 在 $limit 之后,优化器会把 $limit 移动到 $skip 的前面,移动后 $limit的值等于原来的值加上 $skip 的值。

例如:移动前:{$skip: 10, $limit: 5},移动后:{$limit: 15, $skip: 10}

1.4、聚合管道使用限制

对聚合管道的限制主要是对 返回结果大小 和 内存 的限制。

返回结果大小

聚合结果返回的是一个文档,不能超过 16M,从 MongoDB 2.6版本以后,返回的结果可以是一个游标或者存储到集合中,返回的结果不受 16M 的限制。

内存

聚合管道的每个阶段最多只能用 100M 的内存,如果超过100M,会报错,如果需要处理大数据,可以使用 allowDiskUse 选项,存储到磁盘上。

2、单目的聚合操作

单目的聚合命令,常用的:count()、distinct(),与聚合管道相比,单目的聚合操作更简单,使用非常频繁。先通过 distinct() 看一下工作流程

distinct() 的作用是去重。而 count() 是求文档的个数。

下面用 count() 方法举例说明一下

范例

求出集合 article 中 time 值大于 2017-04-09 的文档个数

>db.article.count( { time: { $gt: new Date('04/09/2017') } } )

这个语句等价于

1db.article.find( { time: { $gt: new Date('04/09/2017') } } ).count()

参考:https://blog.csdn.net/qq_37193537/article/details/82388638

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351