3

I'm trying to create a new field in all my documents in a collection. That field will be an array with another field's value as (for now) the single value.

This is my code:

var builder = new UpdateDefinitionBuilder<Member>();
var update = builder.AddToSet(f => f.Sids, "$Sid");

var models = new WriteModel<Member>[]
{
    new UpdateManyModel<Member>(FilterDefinition<Member>.Empty, update)
};

new MongoClient().GetDatabase("mydb").GetCollection<Member>().BulkWrite(models);

It almost worked: the new field (Sids) was created as an array, but with the literal value $Sid instead of the value from the Sid field.

What am I missing?

2 Answers 2

3

great answer by mickl...

starting with mongodb server v4.2 you can refer to existing fields of the documents using aggregation pipeline stages as described here.

in case anybody's interested here's a sample program using MongoDB.Entities doing the same:

using MongoDB.Entities;
using System;
using System.Collections.Generic;

namespace StackOverflow
{
    public class Program
    {
        public class Member : Entity
        {
            public string Sid { get; set; }
        }

        private static void Main(string[] args)
        {
            new DB("test");

            var members = new List<Member>();

            for (int i = 1; i <= 10; i++)
            {
                members.Add(new Member
                {
                    Sid = Guid.NewGuid().ToString()
                });
            }

            members.Save();

            DB.Update<Member>()
              .Match(_ => true)
              .WithPipelineStage("{ '$set': { 'Sids': ['$Sid'] } }")
              .WithPipelineStage("{ '$unset': ['Sid'] }")
              .ExecutePipeline();
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Im currently using your library in one of our projects. It would be great if we could override the save async or save methods in our entites - This would allow us to fire domain events and do auditing on our entites conveniently. Currently we have to do this in the service layer . I wasnt sure how to reach you with this suggestion.
@cl0ud i will look in to it. could you pls open a new issue on github for this? it would help if you show me an example of what you're trying to do, even if it's pseudo code. thanks!
Will post a issue when I get home from work, thanks for your reply. Im also open to creating a pull request and adding it in myself!
2

The dollar sign in updates is not interpreted the same way as it is in Aggregation Framework. Old stackoverflow thread here.

As a workaround you can use $out operator which will replace existing collection with result of aggregation pipeline.

col.Aggregate()
   .AppendStage<BsonDocument>(
                    BsonDocument.Parse("{ $addFields: { \"Sids\": [\"$Sid\"] }}"))
   .Out("col");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.