すべての既存のフィールドを含め、新しいフィールドをドキュメントに追加します


123

$ 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...
]

この場合に使用できる「すべてのフィールドを含める」キーワードのようなもの、またはすべてのフィールドを個別にリストする必要がないようにする他の方法はありますか?


1
この機能は、次のメジャーリリース2.6で提供されます。不安定なdevブランチで試すことができます。「$$ ROOT」を使用して、受信ドキュメント全体を参照してください。このチケットの詳細を参照してください:jira.mongodb.org/browse/SERVER-5916
Asya

1
この問題はstackoverflow.com/questions/20497499/…でも発生し、他の有用で異なる回答がいくつかあります。
Vince Bowdren 16

回答:


168

4.2以降$setでは$addFields、3.4で追加されたエイリアスに他ならない集約パイプライン演算子を使用できます。

この$addFieldsステージは$project、入力ドキュメント内のすべての既存のフィールドを明示的に指定し、新しいフィールドを追加するステージと同等です。

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

2
C#ドライバーでそれを使用する方法はありますか?それは存在しないようです
Homam

私はC#ドライバーに精通していませんが$addFields、MongoDB 3.4の新機能であり、C#ドライバーバージョン
2.5以降で

私はC#ドライバーでこれを行う方法を探していましたが、これまでのところ、それを行う方法は次のようなものを使用しているようですIAggregateFluent<TResult>.AppendStage(new JsonPipelineStageDefinition<TInput, TOutput>("{ $addFields : { myField: 'myValue' }}")
sboisse

4
同じフィールド名を指定した場合、フィールドを置き換えることさえできることを発見しました
CME64

79

$$ ROOTを使用してルートドキュメントを参照できます。このドキュメントのすべてのフィールドをフィールドに保持し、その後に取得してみてください(クライアントシステムによって異なります:Java、C ++など)。

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

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

17
しかし、これはと呼ばれる埋め込まれたドキュメントを作成するdocumentドキュメントは、よりよい...されているだろうマージ作成したものにオプションを
アレクサンダーSuraphel

2
埋め込みドキュメントを作成せずにすべてのキーと値のペアを渡すソリューションを知っている人はいますか?
ugotchi 2016

11
息を止めて。MongoDB 3.4には、これを行う$ addFields集約ステージが付属しています。stackoverflow.com/a/24557029/4653485を参照してください。
ジェローム2016年

(少なくともJSでは)スプレッド演算子を使用して、新しくcustom_fieldアタッチされた元のオブジェクトを再構築できるため、これが現在の最良のソリューションのようです。const newObj = { ...result.document, custom_field: result.custom_field }
ffritz

7

>>>この場合や他の解決策で使用できる「すべてのフィールドを含める」キーワードのようなものはありますか?

残念ながら、集計操作に「すべてのフィールドを含める」演算子はありません。唯一の理由は、集計がコレクションフィールド(合計、平均など)からのデータをグループ化/計算し、すべてのコレクションのフィールドを返すために作成されるためです。これは直接的な目的ではありません。


...集計は主に、コレクションフィールドからのデータをグループ化/計算するために作成されるため...実際、ベストアンサーです。
felipsmartins

1
posts_id、title、body、likesフィールドを含むコレクションがあります。「いいね」フィールドは、投稿を好きなユーザー_idの配列です。すべての_id、title、body、likeCountを含むすべての投稿をどのようにリストできますか?この場合、すべてのフィールドを返すことが直接的な目的です。
doc_id 2017年

3

バージョン2.6.4の時点で、Mongo DBには$project集約パイプライン用のそのような機能がありません。のドキュメントから$project

指定されたフィールドのみのドキュメントをパイプラインの次のステージに渡します。指定されたフィールドは、入力ドキュメントの既存のフィールドまたは新しく計算されたフィールドです。

そして

_idフィールドは、デフォルトで出力ドキュメントに含まれます。入力ドキュメントのその他のフィールドを出力ドキュメントに含めるには、$ projectに含めることを明示的に指定する必要があります。


2

使用できるドキュメントに新しいフィールドを追加するには $addFields

ドキュメントから

ドキュメントのすべてのフィールドに対して、 $$ROOT

db.collection.aggregate([

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

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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.