db.collection.group()

在本页面

Definition

Note

由于db.collection.group()使用 JavaScript,因此它受到许多性能限制。在大多数情况下,aggregation pipeline中的$group运算符提供了一种合适的替代方法,其限制较少。

通过指定的键将集合中的文档分组,并执行简单的聚合功能,例如计算计数和总和。该方法类似于 SQL 中的SELECT <...> GROUP BY语句。 group()方法返回一个数组。

db.collection.group()接受一个包含以下内容的document

Field Type Description
key document 要分组的一个或多个字段。返回一个“键对象”用作分组键。
reduce function 在分组操作期间对文档进行操作的聚合功能。这些函数可以返回总和或计数。该函数采用两个参数:当前文档和该组的汇总结果文档。
initial document 初始化聚合结果文档。
keyf function 可选的。替代key字段。指定一个函数,该函数创建一个“键对象”用作分组键。使用keyf而不是key来按计算字段而不是现有文档字段分组。
cond document 选择标准,以确定要处理集合中的哪些文档。如果省略cond字段,则db.collection.group()处理集合中的所有文档以进行组操作。
finalize function 可选的。在db.collection.group()返回最终值之前运行结果集中每个项目的函数。此功能可以修改结果文档或整体替换结果文档。
collation document Optional.


指定用于操作的collation
Collation允许用户为字符串比较指定特定于语言的规则,例如字母大写和重音符号的规则。
排序规则选项具有以下语法:
collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}
指定排序规则时,locale字段为必填字段;所有其他排序规则字段都是可选的。有关字段的说明,请参见Collation Document
如果未指定排序规则,但是集合具有默认排序规则(请参见db.createCollection()),则该操作将使用为集合指定的排序规则。
如果没有为集合或操作指定排序规则,则 MongoDB 使用先前版本中使用的简单二进制比较进行字符串比较。
您不能为一个操作指定多个排序规则。例如,您不能为每个字段指定不同的排序规则,或者如果对排序执行查找,则不能对查找使用一种排序规则,而对排序使用另一种排序规则。
3.4 版中的新功能。

db.collection.group()方法是group命令的 Shell 程序包装。但是,db.collection.group()方法采用keyf字段和reduce字段,而group命令采用$keyf字段和$reduce字段。

Behavior

限制和限制

db.collection.group()方法不适用于sharded clusters。在sharded environments中使用aggregation frameworkmap-reduce

结果集必须在BSON 文档的最大大小之内。

在 2.2 版中,返回的数组最多可以包含 20,000 个元素;即最多 20,000 个唯一分组。对于导致超过 20,000 个唯一分组的分组操作,请使用mapReduce。以前的版本限制为 10,000 个元素。

在 2.4 之前的版本中,db.collection.group()方法使用了mongod实例的 JavaScript 锁,该锁阻止了所有其他 JavaScript 执行。

mongo Shell JavaScript 函数/属性

map-reduce operationsgroup命令和$where运算符表达式**无法访问mongoShell 程序中可用的某些全局函数或属性,例如db

下列 JavaScript 函数和属性**可用于map-reduce operationsgroup命令和$where运算符表达式:

Available Properties Available Functions
args

MaxKey
MinKey
assert()
BinData()
DBPointer()
DBRef()
doassert()
emit()
gc()
HexData()
hex_md5()
isNumber()
isObject()
ISODate()
isString()
Map()
MD5()
NumberInt()
NumberLong()
ObjectId()
print()
printjson()
printjsononeline()
sleep()
Timestamp()
tojson()
tojsononeline()
tojsonObject()
UUID()
version()

Examples

以下示例假定包含以下原型文档的orders集合:

{
  _id: ObjectId("5085a95c8fada716c89d0021"),
  ord_dt: ISODate("2012-07-01T04:00:00Z"),
  ship_dt: ISODate("2012-07-02T04:00:00Z"),
  item: { sku: "abc123",
          price: 1.99,
          uom: "pcs",
          qty: 25 }
}

按两个字段分组

以下示例按ord_dtitem.sku字段对ord_dt大于01/01/2011的文档进行分组:

db.orders.group(
   {
     key: { ord_dt: 1, 'item.sku': 1 },
     cond: { ord_dt: { $gt: new Date( '01/01/2012' ) } },
     reduce: function ( curr, result ) { },
     initial: { }
   }
)

结果是一组包含按字段分组的文档:

[
  { "ord_dt" : ISODate("2012-07-01T04:00:00Z"), "item.sku" : "abc123"},
  { "ord_dt" : ISODate("2012-07-01T04:00:00Z"), "item.sku" : "abc456"},
  { "ord_dt" : ISODate("2012-07-01T04:00:00Z"), "item.sku" : "bcd123"},
  { "ord_dt" : ISODate("2012-07-01T04:00:00Z"), "item.sku" : "efg456"},
  { "ord_dt" : ISODate("2012-06-01T04:00:00Z"), "item.sku" : "abc123"},
  { "ord_dt" : ISODate("2012-06-01T04:00:00Z"), "item.sku" : "efg456"},
  { "ord_dt" : ISODate("2012-06-01T04:00:00Z"), "item.sku" : "ijk123"},
  { "ord_dt" : ISODate("2012-05-01T04:00:00Z"), "item.sku" : "abc123"},
  { "ord_dt" : ISODate("2012-05-01T04:00:00Z"), "item.sku" : "abc456"},
  { "ord_dt" : ISODate("2012-06-08T04:00:00Z"), "item.sku" : "abc123"},
  { "ord_dt" : ISODate("2012-06-08T04:00:00Z"), "item.sku" : "abc456"}
]

方法调用类似于 SQL 语句:

SELECT ord_dt, item_sku
FROM orders
WHERE ord_dt > '01/01/2012'
GROUP BY ord_dt, item_sku

计算总和

以下示例按ord_dtitem.sku字段分组,这些文档的ord_dt大于01/01/2011并为每个分组计算qty字段的总和:

db.orders.group(
   {
     key: { ord_dt: 1, 'item.sku': 1 },
     cond: { ord_dt: { $gt: new Date( '01/01/2012' ) } },
     reduce: function( curr, result ) {
                 result.total += curr.item.qty;
             },
     initial: { total : 0 }
   }
)

结果是一个文档数组,其中包含 group by 字段和计算出的聚合字段:

[ { "ord_dt" : ISODate("2012-07-01T04:00:00Z"), "item.sku" : "abc123", "total" : 25 },
  { "ord_dt" : ISODate("2012-07-01T04:00:00Z"), "item.sku" : "abc456", "total" : 25 },
  { "ord_dt" : ISODate("2012-07-01T04:00:00Z"), "item.sku" : "bcd123", "total" : 10 },
  { "ord_dt" : ISODate("2012-07-01T04:00:00Z"), "item.sku" : "efg456", "total" : 10 },
  { "ord_dt" : ISODate("2012-06-01T04:00:00Z"), "item.sku" : "abc123", "total" : 25 },
  { "ord_dt" : ISODate("2012-06-01T04:00:00Z"), "item.sku" : "efg456", "total" : 15 },
  { "ord_dt" : ISODate("2012-06-01T04:00:00Z"), "item.sku" : "ijk123", "total" : 20 },
  { "ord_dt" : ISODate("2012-05-01T04:00:00Z"), "item.sku" : "abc123", "total" : 45 },
  { "ord_dt" : ISODate("2012-05-01T04:00:00Z"), "item.sku" : "abc456", "total" : 25 },
  { "ord_dt" : ISODate("2012-06-08T04:00:00Z"), "item.sku" : "abc123", "total" : 25 },
  { "ord_dt" : ISODate("2012-06-08T04:00:00Z"), "item.sku" : "abc456", "total" : 25 } ]

方法调用类似于 SQL 语句:

SELECT ord_dt, item_sku, SUM(item_qty) as total
FROM orders
WHERE ord_dt > '01/01/2012'
GROUP BY ord_dt, item_sku

计算总和,计数和平均值

以下示例按计算出的day_of_week字段(大于01/01/2011 ord_dt的那些文档)进行分组,并为每个分组计算qty字段的总和,计数和平均值:

db.orders.group(
   {
     keyf: function(doc) {
               return { day_of_week: doc.ord_dt.getDay() };
           },
     cond: { ord_dt: { $gt: new Date( '01/01/2012' ) } },
    reduce: function( curr, result ) {
                result.total += curr.item.qty;
                result.count++;
            },
    initial: { total : 0, count: 0 },
    finalize: function(result) {
                  var weekdays = [
                       "Sunday", "Monday", "Tuesday",
                       "Wednesday", "Thursday",
                       "Friday", "Saturday"
                      ];
                  result.day_of_week = weekdays[result.day_of_week];
                  result.avg = Math.round(result.total / result.count);
              }
   }
)

结果是一个文档数组,其中包含 group by 字段和计算出的聚合字段:

[
  { "day_of_week" : "Sunday", "total" : 70, "count" : 4, "avg" : 18 },
  { "day_of_week" : "Friday", "total" : 110, "count" : 6, "avg" : 18 },
  { "day_of_week" : "Tuesday", "total" : 70, "count" : 3, "avg" : 23 }
]

See also

Aggregation

首页