MongoDB - 对象?为什么我需要聚合_id

时间:2015-06-08 22:03:37

标签: mongodb aggregation-framework

以下是MongoDB教程的示例(此处为集合ZIP Code db

db.zipcodes.aggregate( [
   { $group: { _id: "$state", totalPop: { $sum: "$pop" } } },
   { $match: { totalPop: { $gte: 10*1000*1000 } } }
] )

如果我将_id替换为其他字词Test,我会收到错误消息:

"errmsg" : "exception: the group aggregate field 'Test' must be defined as an expression inside an object",
"code" : 15951,
"ok" : 0

有人能帮助我理解为什么我的命令需要_id吗?我认为MongoDB会自动分配ID,如果使用则不提供ID。

3 个答案:

答案 0 :(得分:6)

$group阶段,_id用于指定组条件。你显然需要它。

如果您熟悉SQL世界,请将其视为GROUP BY子句。

请注意,在该上下文中,_id实际上是生成的集合中的唯一标识符,因为根据定义$group不能生成具有该字段相同值的两个文档。 /子>

答案 1 :(得分:5)

我们将了解_id阶段内的$group字段&查看在组聚合阶段构建_id的一些最佳实践。我们来看看这个查询:


db.companies.aggregate([{
  $match: {
    founded_year: {
      $gte: 2010
    }
  }
}, {
  $group: {
    _id: {
      founded_year: "$founded_year"
    },
    companies: {
      $push: "$name"
    }
  }
}, {
  $sort: {
    "_id.founded_year": 1
  }
}]).pretty()

MongoDB $group with document approach

我们可能不清楚的一件事是为什么_id字段是以这种“文档”方式构建的?我们也可以这样做:


db.companies.aggregate([{
  $match: {
    founded_year: {
      $gte: 2010
    }
  }
}, {
  $group: {
    _id: "$founded_year",
    companies: {
      $push: "$name"
    }
  }
}, {
  $sort: {
    "_id": 1
  }
}]).pretty()

MongoDB $group without document approach

我们不是这样做的,因为在这些输出文件中 - 这个数字究竟意味着什么并不明确。所以,我们实际上不知道。在某些情况下,这意味着在解释这些文件时可能会有困惑。因此,另一种情况可能是将_id文档分组为多个字段:


db.companies.aggregate([{
  $match: {
    founded_year: {
      $gte: 2010
    }
  }
}, {
  $group: {
    _id: {
      founded_year: "$founded_year",
      category_code: "$category_code"
    },
    companies: {
      $push: "$name"
    }
  }
}, {
  $sort: {
    "_id.founded_year": 1
  }
}]).pretty()

group an _id document with multiple fields in MongoDB

$push只是将元素推送到生成数组。通常,可能需要将提升的字段分组到较高级别:


db.companies.aggregate([{
  $group: {
    _id: {
      ipo_year: "$ipo.pub_year"
    },
    companies: {
      $push: "$name"
    }
  }
}, {
  $sort: {
    "_id.ipo_year": 1
  }
}]).pretty()

group on promoted fields to upper level in MongoDB

将表达式解析为文档作为_id密钥也是完美的。

db.companies.aggregate([{
  $match: {
    "relationships.person": {
      $ne: null
    }
  }
}, {
  $project: {
    relationships: 1,
    _id: 0
  }
}, {
  $unwind: "$relationships"
}, {
  $group: {
    _id: "$relationships.person",
    count: {
      $sum: 1
    }
  }
}, {
  $sort: {
    count: -1
  }
}])

It's also perfect to have an expression that resolves to a document as a _id key in MongoDB

答案 2 :(得分:4)

_id字段是必填字段,但如果希望根据密钥或密钥进行汇总,则可以将其设置为null。不使用它将导致字段上的单个聚合值。因此,它在此上下文中表示“保留字”,指示每个组产生的“标识符”/键是什么。

在您的情况下,按_id: "$state"分组会产生n totalPop的汇总结果,前提是nstate个不同的值(类似)到SELECT SUM() FROM table GROUP BY state)。然而,

$group : {_id : null, totalPop: { $sum: "$pop" }}}

会为totalPop提供单一结果(类似于SELECT SUM() FROM table)。

组操作符documentation中详细描述了此行为。