Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Addfields in MongoDB C# Aggregation Pipeline

Mongo DB's Aggregation pipeline has an "AddFields" stage that allows you to project new fields to the pipeline's output document without knowing what fields already existed.

It seems this has not been included in the C# driver for Mongo DB (using version 2.7).

Does anyone know if there are any alternatives to this? Maybe a flag on the "Project" stage?

like image 394
tajay Avatar asked Nov 03 '18 16:11

tajay


People also ask

How to use$ addFields in MongoDB?

Definition. Adds new fields to documents. $addFields outputs documents that contain all existing fields from the input documents and newly added fields. The $addFields stage is equivalent to a $project stage that explicitly specifies all existing fields in the input documents and adds the new fields.

How to create a field in MongoDB?

MongoDB add fieldRight-click on any cell while in Table View or Tree View. Go to Field > Add Field/Value. Choose the right field type (e.g. String). Define the field value (e.g. green).

What is $first in MongoDB?

This means $first returns the first order type for the documents between the beginning of the partition and the current document.

What is Pipelining in MongoDB?

What is the Aggregation Pipeline in MongoDB? The aggregation pipeline refers to a specific flow of operations that processes, transforms, and returns results. In a pipeline, successive operations are informed by the previous result. Let's take a typical pipeline: Input -> $match -> $group -> $sort -> output.


2 Answers

I'm not sure all the BsonDocument usage is required. Certainly not in this example where I append the textScore of a text search to the search result.

        private IAggregateFluent<ProductTypeSearchResult> CreateSearchQuery(string query)
        {
            FilterDefinition<ProductType> filter = Builders<ProductType>.Filter.Text(query);
            return _collection
                .Aggregate()
                .Match(filter)
                .AppendStage<ProductType>("{$addFields: {score: {$meta:'textScore'}}}")
                .Sort(Sort)
                .Project(pt => new ProductTypeSearchResult
                {
                    Description = pt.ExternalProductTypeDescription,
                    Id = pt.Id,
                    Name = pt.Name,
                    ProductFamilyId = pt.ProductFamilyId,
                    Url = !string.IsNullOrEmpty(pt.ShopUrl) ? pt.ShopUrl : pt.TypeUrl,
                    Score = pt.Score
                });
        }

Note that ProductType does have a Score property defined as

        [BsonIgnoreIfNull]
        public double Score { get; set; }

It's unfortunate that $addFields is not directly supported and we have to resort to "magic strings"

like image 167
Richard Collette Avatar answered Oct 05 '22 20:10

Richard Collette


As discussed here Using $addFields in MongoDB Driver for C# you can build the aggregation stage yourself with a BsonDocument.

To use the example from https://docs.mongodb.com/manual/reference/operator/aggregation/addFields/

{
  $addFields: {
    totalHomework: { $sum: "$homework" } ,
    totalQuiz: { $sum: "$quiz" }
  }
}

would look something like this:

BsonDocument expression = new BsonDocument(new List<BsonElement>() {
    new BsonElement("totalHomeWork", new BsonDocument(new BsonElement("$sum", "$homework"))),
    new BsonElement("totalQuiz", new BsonDocument(new BsonElement("$sum", "$quiz")))
});
BsonDocument addFieldsStage = new BsonDocument(new BsonElement("$addFields", expression));
IAggregateFluent<BsonDocument> aggregate = col.Aggregate().AppendStage(addFieldsStage);

expression being the BsonDocument representing

{
  totalHomework: { $sum: "$homework" } ,
  totalQuiz: { $sum: "$quiz" }
}

You can append additional stages onto the IAggregateFluent Object as normal

IAggregateFluent<BsonDocument> aggregate = col.Aggregate()
    .Match(filterDefintion)
    .AppendStage(addFieldsStage)
    .Project(projectionDefintion);
like image 20
FalcoGer Avatar answered Oct 05 '22 21:10

FalcoGer