How to use Addfields in MongoDB C# Aggregation Pipeline

那年仲夏 提交于 2019-12-05 18:13:54

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);

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"

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!