是否可以在 mongo 的组聚合后重命名 _id 字段?
Posted
技术标签:
【中文标题】是否可以在 mongo 的组聚合后重命名 _id 字段?【英文标题】:Is it possible to rename _id field after mongo's group aggregation? 【发布时间】:2017-09-18 04:11:57 【问题描述】:我有一个这样的查询(简化):
db.collection.aggregate([
$match: main_id: ObjectId("58f0f67f50c6af16709fd2c7") ,
$group:
_id: "$name",
count: $sum: 1 ,
sum: $sum: $add: ["$P31", "$P32"]
])
我从 Java 执行此查询,我想将它映射到我的班级,但我不希望将 _id
映射到 name
字段。因为如果我这样做:
@JsonProperty("_id")
private String name;
然后,当我将此数据保存回 mongo(经过一些修改)时,数据以名称保存为 _id
,而我希望生成一个真实的 Id。
那么,我如何在$group
操作之后重命名 _id
?
【问题讨论】:
$project 它在管道的下一个阶段 【参考方案1】:您可以通过在管道末尾添加$project
阶段来实现这一点,如下所示:
$project:
_id: 0,
name: "$_id",
count: 1,
sum: 1
在线试用:mongoplayground.net/p/QpVyh-0I-bP
【讨论】:
【参考方案2】:从 mongo v3.4 开始,您可以将$addFields
与$project
结合使用,以避免在$project
中写入可能非常乏味的所有字段。
这发生在$project
中,因为如果您专门包含一个字段,其他字段将被自动排除。
例子:
$addFields: my_new_id_name: "$_id"
,
$project: _id: 0
【讨论】:
对我不起作用,我得到$projection requires at least one output field.
(在聚合中使用它)
澄清:我在 AWS 中使用 DocumentDB
它工作正常,但我需要将_id转换为字符串,所以 $addFields: id: $toString: '$_id'
和管道的顺序应该得到尊重,首先$addFields
和$project
。【参考方案3】:
db.report.aggregate(
$group: _id: '$name'
,
$project:
name:"$_id",
_id:false
)
【讨论】:
【参考方案4】:如果你使用find
方法你不能这样做,但如果你使用aggregation
这很简单:
db.collectionName.aggregate([
$project:
newName: "$existingKeyName"
]);
【讨论】:
【参考方案5】:从Mongo 4.2
开始,您可以使用$set
/ $unset
阶段的组合:
// x: 1, z: "a"
// x: 2, z: "b"
db.collection.aggregate([
$set: y: "$x" ,
$unset: "x"
])
// y: 1, z: "a"
// y: 2, z: "b"
$set
阶段将新字段添加到文档中,$unset
阶段从文档中删除/排除要重命名的字段。
【讨论】:
【参考方案6】:由于所有答案都是在 MongoDB 查询中编写的解决方案,尽管该问题在 Java 中寻求解决方案,因此将我使用 Java 的方法发布给后代。
分组后,我们可以使用重命名_id
字段名
Projections.computed("<expected field name>", "$_id")))
将问题中提到的查询的核心部分转换为Java
Bson mainIdMatch = match(eq("main_id", new ObjectId("58f0f67f50c6af16709fd2c7")));
Bson group = Aggregates.group("$name", Accumulators.sum("count", 1L));
Bson project = Aggregates.project(Projections.fields(Projections.excludeId(),
Projections.computed("name", "$_id")));
reportMongoCollection.aggregate(Arrays.asList(mainIdMatch, group, project))
.into(new ArrayList<>());
为了具体回答,我添加了上述代码 sn-p 的摘录,其中我使用 Projections.computed("name", "$_id")
将 _id
字段值重命名为名称,它映射了我们得到的 _id
的值分组到名为name
的字段。此外,我们应该使用 Projections.excludeId()
排除 id。
Aggregates.project(Projections.fields(Projections.excludeId(),
Projections.computed("name", "$_id")))
【讨论】:
以上是关于是否可以在 mongo 的组聚合后重命名 _id 字段?的主要内容,如果未能解决你的问题,请参考以下文章
mongodb Aggregation聚合操作之$bucket