On this page
group
在本页面
Definition
group
- 从 3.4 版开始不推荐使用:Mongodb 3.4 不推荐使用group命令。将db.collection.aggregate()与$group阶段或db.collection.mapReduce()结合使用。
Note
由于group使用 JavaScript,因此它受到许多性能限制。在大多数情况下,aggregation pipeline中的$group运算符提供了一种合适的替代方法,其限制较少。
通过指定的键将集合中的文档分组,并执行简单的聚合功能,例如计算计数和总和。该命令类似于 SQL 中的SELECT <...> GROUP BY
语句。该命令返回包含分组记录以及命令元数据的文档。
group命令采用以下原型形式:
{
group:
{
ns: <namespace>,
key: <key>,
$reduce: <reduce function>,
$keyf: <key function>,
cond: <query>,
finalize: <finalize function>
}
}
该命令接受具有以下字段的文档:
Field | Type | Description |
---|---|---|
ns |
string | 从中执行分组操作的集合。 |
key |
document | 要分组的一个或多个字段。返回一个“键对象”用作分组键。 |
$reduce |
function | 在分组操作期间对文档进行操作的聚合功能。这些函数可以返回总和或计数。该函数采用两个参数:当前文档和该组的汇总结果文档。 |
initial |
document | 初始化聚合结果文档。 |
$keyf |
function | 可选的。替代key 字段。指定一个函数,该函数创建一个“键对象”用作分组键。使用$keyf 而不是key 来按计算字段而不是现有文档字段分组。 |
cond |
document | 可选的。选择标准,以确定要处理集合中的哪些文档。如果省略cond 字段,则group处理集合中的所有文档以进行组操作。 |
finalize |
function | 可选的。在group返回最终值之前运行结果集中每个项目的函数。此功能可以修改结果文档或整体替换结果文档。与也指定功能的$keyf 和$reduce 字段不同,此字段名称是finalize ,不是 $finalize 。 |
对于 Shell,MongoDB 提供了包装器方法db.collection.group()。但是,db.collection.group()方法采用keyf
字段和reduce
字段,而group命令采用$keyf
字段和$reduce
字段。
Behavior
限制和限制
group命令不适用于sharded clusters。在sharded environments中使用aggregation framework或map-reduce。
结果集必须在BSON 文档的最大大小之内。
此外,在 2.2 版中,返回的数组最多可以包含 20,000 个元素;即最多 20,000 个唯一分组。对于导致超过 20,000 个唯一分组的分组操作,请使用mapReduce。以前的版本限制为 10,000 个元素。
在 2.4 之前的版本中,group命令获得了mongod实例的 JavaScript 锁,该锁阻止了所有其他 JavaScript 执行。
mongo Shell JavaScript 函数/属性
map-reduce operations,group命令和$where运算符表达式**无法访问mongoShell 程序中可用的某些全局函数或属性,例如db
。
下列 JavaScript 函数和属性**可用于map-reduce operations,group命令和$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() |
JavaScript in MongoDB
尽管group使用 JavaScript,但是大多数与 MongoDB 的交互都不使用 JavaScript,而是使用idiomatic driver作为交互应用程序的语言。
Examples
以下是db.collection.group()方法的示例。这些示例假定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_dt
和item.sku
字段对ord_dt
大于01/01/2012
的文档进行分组:
db.runCommand(
{
group:
{
ns: 'orders',
key: { ord_dt: 1, 'item.sku': 1 },
cond: { ord_dt: { $gt: new Date( '01/01/2012' ) } },
$reduce: function ( curr, result ) { },
initial: { }
}
}
)
结果是一个文档,其中包含retval
字段,该字段包含按记录分组; count
字段,该字段包含分组的文档总数; keys
字段,该字段包含唯一分组的数量(即retval
中的元素数量);以及ok
字段,其中包含命令状态:
{ "retval" :
[ { "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"}
],
"count" : 13,
"keys" : 11,
"ok" : 1 }
方法调用类似于 SQL 语句:
SELECT ord_dt, item_sku
FROM orders
WHERE ord_dt > '01/01/2012'
GROUP BY ord_dt, item_sku
计算总和
以下示例通过ord_dt
和item.sku
字段对ord_dt
大于01/01/2012
的那些文档进行分组,并为每个分组计算qty
字段的总和:
db.runCommand(
{ group:
{
ns: 'orders',
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 }
}
}
)
返回文档的retval
字段是一个文档数组,其中包含 group by 字段和计算出的聚合字段:
{ "retval" :
[ { "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 }
],
"count" : 13,
"keys" : 11,
"ok" : 1 }
方法调用类似于 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/2012
ord_dt
的那些文档)进行分组,并为每个分组计算qty
字段的总和,计数和平均值:
db.runCommand(
{
group:
{
ns: 'orders',
$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);
}
}
}
)
返回文档的retval
字段是一个文档数组,其中包含 group by 字段和计算出的聚合字段:
{
"retval" :
[
{ "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 }
],
"count" : 13,
"keys" : 3,
"ok" : 1
}
See also