ChatGPT解决这个技术问题 Extra ChatGPT

包括所有现有字段并将新字段添加到文档

我想定义一个 $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...
]

在这种情况下,是否可以使用类似于“包含所有字段”的关键字,或者通过其他方式避免必须单独列出每个字段?

此功能将在下一个主要版本 2.6 中提供。您可以在不稳定的开发分支上尝试它 - 使用“$$ROOT”来引用整个传入文档。请参阅此票证中的详细信息:jira.mongodb.org/browse/SERVER-5916
stackoverflow.com/questions/20497499/… 也提出了这个问题,并提供了一些其他有用且不同的答案。

K
Kaspar Lee

在 4.2+ 中,您可以使用 $set 聚合管道运算符,它只是 3.4 中添加的 $addFields 的别名

$addFields 阶段相当于 $project 阶段,它明确指定输入文档中的所有现有字段并添加新字段。

db.collection.aggregate([
    { "$addFields": { "custom_field": "$obj.obj_field1" } }
])

知道如何在 C# 驱动程序中使用它吗?好像不存在
我不熟悉 C# 驱动程序,但 $addFields 是 MongoDB 3.4 中的新功能,受 C# driver version 2.5+ 支持
我一直在寻找在 C# 驱动程序中执行此操作的方法,到目前为止,执行此操作的方法似乎是使用 IAggregateFluent<TResult>.AppendStage(new JsonPipelineStageDefinition<TInput, TOutput>("{ $addFields : { myField: 'myValue' }}")
我发现如果您指定相同的字段名称,它甚至可以替换字段
D
Deka

您可以使用 $$ROOT 来引用根文档。将此文档的所有字段保存在一个字段中,然后尝试获取它(取决于您的客户端系统:Java、C++、...)

 [
    {
        $project: {
            custom_field: "$obj.obj_field1",
            document: "$$ROOT"

        }
    },
    ... //group, match, and whatever...
]

但这将创建一个名为 document 的嵌入式文档,创建一个合并文档的选项会更好......
有谁知道在不创建嵌入式文档的情况下通过所有键值对的解决方案?
屏住呼吸。 MongoDB 3.4 将附带执行此操作的 $addFields aggregation stage。见stackoverflow.com/a/24557029/4653485
这似乎是当前最好的解决方案,因为您可以(至少在 JS 中)然后使用扩展运算符重建原始对象并附加新的 custom_fieldconst newObj = { ...result.document, custom_field: result.custom_field }
V
Victoria Malaya

>>> 在这种情况下我可以使用“包含所有字段”关键字或其他解决方案吗?

不幸的是,聚合操作中没有运算符可以“包含所有字段”。唯一的原因是,因为创建聚合主要是为了对集合字段(sum、avg 等)中的数据进行分组/计算并返回所有集合的字段,这不是直接目的。


...因为聚合主要是为了对集合字段中的数据进行分组/计算而创建的...事实上是最佳答案!
您有一个集合 posts,其中包含 _id、title、body、like 字段。 likes 字段是一个喜欢帖子的用户 _id 数组。你怎么能列出所有带有_id、标题、正文、likeCount 的帖子?在这种情况下,返回所有字段是一个直接目的。
A
Akj

要向文档添加新字段,您可以使用 $addFields

from docs

对于文档中的所有字段,您可以使用 $$ROOT

db.collection.aggregate([

{ "$addFields": { "custom_field": "$obj.obj_field1" } },
{ "$group": {
        _id : "$field1",
        data: { $push : "$$ROOT" }
    }}
])

他想要根目录中的所有字段。这将添加文档数组下的所有字段。
G
Ghopper21

从 2.6.4 版本开始,Mongo DB 没有用于 $project 聚合管道的此类功能。从 docs$project

将仅具有指定字段的文档传递到管道中的下一个阶段。指定的字段可以是输入文档中的现有字段或新计算的字段。

默认情况下,_id 字段包含在输出文档中。要将输入文档中的其他字段包含在输出文档中,您必须在 $project 中明确指定包含。


m
mr.byte

根据@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);

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅