我想定义一个$ project聚合阶段,我可以指示它添加一个新字段并包含所有现有字段,而不必列出所有现有字段。
我的文档看起来像这样,有很多字段:
{
obj: {
obj_field1: "hi",
obj_field2: "hi2"
},
field1: "a",
field2: "b",
...
field26: "z"
}
我想进行这样的聚合操作:
[
{
$project: {
custom_field: "$obj.obj_field1",
//the next part is that I don't want to do
field1: 1,
field2: 1,
...
field26: 1
}
},
... //group, match, and whatever...
]
在这种情况下,我可以使用类似“包含所有字段”的关键字,还是以其他方式避免必须单独列出每个字段?
答案 0 :(得分:131)
从MongoDB 3.4开始,我们可以使用$addFields
聚合管道运算符来执行此操作:
$addFields
阶段相当于$project
阶段,该阶段明确指定输入文档中的所有现有字段并添加新字段。
db.collection.aggregate([
{ "$addFields": { "custom_field": "$obj.obj_field1" } }
])
答案 1 :(得分:66)
您可以使用$$ROOT来引用根文档。将此文档的所有字段保留在一个字段中,然后尝试获取它(取决于您的客户端系统:Java,C ++,...)
[
{
$project: {
custom_field: "$obj.obj_field1",
document: "$$ROOT"
}
},
... //group, match, and whatever...
]
答案 2 :(得分:6)
>>>在这种情况下我可以使用“包括所有字段”关键字或其他解决方案吗?
不幸的是,在聚合操作中没有“包括所有字段”的运算符。唯一的原因,原因,因为聚合主要是为了从集合字段(sum,avg等)分组/计算数据并返回所有集合的字段而不是直接目的。
答案 3 :(得分:2)
从版本2.6.4开始,Mongo DB没有$project
聚合管道的这种功能。来自$project
的{{3}}:
将仅包含指定字段的文档传递到管道中的下一个阶段。指定的字段可以是输入文档或新计算字段中的现有字段。
和
默认情况下,_id字段包含在输出文档中。要在输出文档中包含输入文档中的其他字段,必须在$ project中明确指定包含。
答案 4 :(得分:0)
根据@Deka的回复,对于c#mongodb驱动程序2.5,您可以使用如下所有键获取分组文档;
var group = new BsonDocument
{
{ "_id", "$groupField" },
{ "_document", new BsonDocument { { "$first", "$$ROOT" } } }
};
ProjectionDefinition<BsonDocument> projection = new BsonDocument{{ "document", "$_document"}};
var result = await col.Aggregate().Group(group).Project(projection).ToListAsync();
// For demo first record
var fistItemAsT = BsonSerializer.Deserialize<T>(result.ToArray()[0]["document"].AsBsonDocument);
答案 5 :(得分:0)
要向文档中添加新字段,可以使用$ addFields
[来自文档] [1]
在文档的所有字段中,您都可以使用$$ ROOT
db.collection.aggregate([
{ "$addFields": { "custom_field": "$obj.obj_field1" } },
{ "$group": {
_id : "$field1",
data: { $push : "$$ROOT" }
}}
])
[1]: https://docs.mongodb.com/master/reference/operator/aggregation/addFields/