我想定义一个 $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...
]
在这种情况下,是否可以使用类似于“包含所有字段”的关键字,或者通过其他方式避免必须单独列出每个字段?
在 4.2+ 中,您可以使用 $set
聚合管道运算符,它只是 3.4 中添加的 $addFields
的别名
$addFields 阶段相当于 $project 阶段,它明确指定输入文档中的所有现有字段并添加新字段。
db.collection.aggregate([
{ "$addFields": { "custom_field": "$obj.obj_field1" } }
])
您可以使用 $$ROOT 来引用根文档。将此文档的所有字段保存在一个字段中,然后尝试获取它(取决于您的客户端系统:Java、C++、...)
[
{
$project: {
custom_field: "$obj.obj_field1",
document: "$$ROOT"
}
},
... //group, match, and whatever...
]
document
的嵌入式文档,创建一个合并文档的选项会更好......
custom_field
。 const newObj = { ...result.document, custom_field: result.custom_field }
>>> 在这种情况下我可以使用“包含所有字段”关键字或其他解决方案吗?
不幸的是,聚合操作中没有运算符可以“包含所有字段”。唯一的原因是,因为创建聚合主要是为了对集合字段(sum、avg 等)中的数据进行分组/计算并返回所有集合的字段,这不是直接目的。
posts
,其中包含 _id、title、body、like 字段。 likes 字段是一个喜欢帖子的用户 _id 数组。你怎么能列出所有带有_id、标题、正文、likeCount 的帖子?在这种情况下,返回所有字段是一个直接目的。
要向文档添加新字段,您可以使用 $addFields
对于文档中的所有字段,您可以使用 $$ROOT
db.collection.aggregate([
{ "$addFields": { "custom_field": "$obj.obj_field1" } },
{ "$group": {
_id : "$field1",
data: { $push : "$$ROOT" }
}}
])
从 2.6.4 版本开始,Mongo DB 没有用于 $project
聚合管道的此类功能。从 docs 到 $project
:
将仅具有指定字段的文档传递到管道中的下一个阶段。指定的字段可以是输入文档中的现有字段或新计算的字段。
和
默认情况下,_id 字段包含在输出文档中。要将输入文档中的其他字段包含在输出文档中,您必须在 $project 中明确指定包含。
根据@Deka 的回复,对于 c# mongodb driver 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);
$addFields
是 MongoDB 3.4 中的新功能,受 C# driver version 2.5+ 支持IAggregateFluent<TResult>.AppendStage(new JsonPipelineStageDefinition<TInput, TOutput>("{ $addFields : { myField: 'myValue' }}")