[CSHARP-1750] Add support for $addFields aggregation stage Created: 19/Aug/16  Updated: 04/May/23  Resolved: 29/Aug/16

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major - P3
Reporter: Rathi Gnanasekaran Assignee: Unassigned
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
depends on SERVER-5781 Implement $addFields aggregation stag... Closed
Epic Link: MongoDB 3.4
Server Compat: 3.3

 Description   

As of 3.3.11, we added the $addFields aggregation stage:

Syntax

{$addFields: {newFieldName1: <Expression1>, ...}}

Examples

// =====  Example #1 - Adding a literal field value =====
>db.example.insert({_id: 0, a: 1})
>db.example.aggregate([{$addFields: {newField: “hello”}}]);
{_id: 0, a: 1, newField: “hello”}
 
// =====  Example #2 - Adding a value from a field path =====
>db.example.insert({_id: 0, a: 1})
>db.example.aggregate([{$addFields: {b: “$a”}}])
{_id: 0, a: 1, b: 1}
 
// =====  Example #3 - Adding a value from a system variable =====
>db.example.insert({_id: 0, a: 1})
>db.example.aggregate([{$addFields: {this: “$$CURRENT”}}])
{_id: 0, a: 1, this: {_id: 0, a: 1}}
 
// =====  Example #4 - Adding a value from an expression object =====
>db.example.insert({_id: 0, a: 1})
>db.example.aggregate([{$addFields: {myNewField: {c: 3, d: 4}}}])
{_id: 0, a: 1, myNewField: {c: 3, d: 4}}
 
// =====  Example #5 - Adding a value from an operator expression =====
>db.example.insert({_id: 0, a: 1})
>db.example.aggregate([{$addFields: {alt3: {$lt: [“$a”, 3]}}}])
{_id: 0, a: 1, alt3: true}
 
// =====  Example #6 Adding multiple new fields at once =====
>db.example.insert({_id: 0, a: 1})
>db.example.aggregate([{$addFields: {b: 3, c: 5}}])
{_id: 0, a: 1, b: 3, c: 5}
 
// =====  Example #6 - Setting a field that already exists =====
>db.example.insert({_id: 0, a: 1})
>db.example.aggregate([{$addFields: {a: [1, 2, 3]}}])
{_id: 0, a: [1, 2, 3]}

Original Description

It would be great if you could use $project (or something) to decorate the input object with additional, calculated values. This way, you wouldn't need to explicitly name all the fields that you want to carry forward if you just need to add calculated values.

For example, currently, in a collection with the following document:

{_id: 0, foo: 1, bar: 1}

When you run the following pipeline:

db.coll.aggregate([{$project: {newField: {$add: [1, '$foo']}}}])

You get the following document:

{_id: 0, newField: 2}

This is requesting that there be some way to get the following document (with all original fields present), without knowing which fields are in the original document:

{_id: 0, foo: 1, bar: 1, newField: 2}

This could be accomplished by adding some option to the $project stage, e.g.

db.coll.aggregate([{$project: {newField: {$add: [1, '$foo']}, $keepExisting: true}}])

Or by adding a new stage, e.g.

db.coll.aggregate([{$set: {newField: {$add: [1, '$foo']}}])



 Comments   
Comment by Corey Forbes [ 04/May/23 ]

I was trying to use this $addField/$set functionality to add a value to a pre-modeled document that contains a dictionary. This could not be pre-calculated for the document to save but instead the storage depends on input factors and at run time e.g. Which queries did this specific document meet so that we can next sort and paginate appropriately. This would be great to see revisited.

Comment by Christopher Sena [ 08/May/17 ]

But this can apply to a type-safe API the result can just be cast to the a new type (with the extra field).
If whilst defining an aggregation I would like to add an extra field in a strongly typed way and cast the resulting document I am currently forced to redefine each field separately.

Doesn't this miss the whole point of the $addFields aggregation stage?

Surely this could be achieved in C# with something like..

IAggregateFluent<TNewResult> AddField<TResult,TNewResult>(Expression<Func<TResult, TField>> newFieldExpression, Expression<Func<TNewResult, TField>> newFieldLocation)

Sort of similar to how a lookup is added. This would really help.
I was quite surprised that the C# driver does not support this. Am I just missing something?

Comment by Craig Wilson [ 29/Aug/16 ]

This doesn't apply to a type-safe API, so nothing to do for LINQ.

Generated at Wed Feb 07 21:40:34 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.