Search code examples
c#.netmongodbmongodb-.net-driver

Rename nested field in BsonDocument with MongoDB.Driver


I have a document, it contains a CustomFields document, in which there are still documents.

How to correctly update the Checkpoint Comment document name to the Checkpoint Comment-test.

I tried as below but it doesn't work.

var filter = Builders<Visit>.Filter;

UpdateDefinition<Visit> update = Builders<Visit>.Update.Rename(x => x.CustomFields.FirstOrDefault(f => f.Name == "Сheckpoint Comment").Name, "Сheckpoint Comment-test");
Collection.UpdateMany(filter.Where(x => true), update);
{
  "_id": ObjectId("61e5707d23516865481ebee7"),
  "CustomFields": {
    "Сheckpoint Comment": {
      "FieldId": ObjectId("6149d5de44175b8324482904"),
      "Type": "Text",
      "ValueBson": "test"
    },
    "Time of arrival at the checkpoint": {
      "FieldId": ObjectId("6149d5de44175b8324482905"),
      "Type": "DateTime",
      "ValueBson": null
    }
  }
}

Solution

  • Solutions

    Solution 1

    If you apply [BsonElement] attribute to the class' property as below:

    public class Visit
    {
        public ObjectId Id { get; set; }
        public CustomField CustomFields { get; set; }
    }
    
    public class CustomField
    {
        [BsonElement("Сheckpoint Comment")]
        public BsonProp Checkpoint { get; set; }
        [BsonElement("Time of arrival at the checkpoint")]
        public BsonProp Time { get; set; }
    }
    
    public class BsonProp
    {
       public ObjectId FieldId { get; set; }
       public string Type { get; set; }
       public string ValueBson { get; set; }
    }
    

    Then specify your field to be renamed as:

    UpdateDefinition<Visit> update = Builders<Visit>.Update.Rename(x => x.CustomFields.Checkpoint, "CustomFields.Сheckpoint Comment-test");
    Collection.UpdateMany(filter.Empty, update);
    

    Solution 2

    Without applying [BsonElement] attribute, just specify the field to be renamed in string.

    UpdateDefinition<Visit> update = Builders<Visit>.Update.Rename("CustomFields.Сheckpoint Comment", "CustomFields.Сheckpoint Comment-test");
    Collection.UpdateMany(filter.Empty, update);
    

    Concern & Suggestion

    1. The field after rename needs with prefix CustomFields. as "CustomFields.Сheckpoint Comment-test" because you are updating the nested field in an object. Without the prefix CustomFields., Сheckpoint Comment-test will be at the same level as CustomFields, but not inside the CustomFields object.

    2. The filter with

    filter.Where(x => true)
    

    can be replaced with

    filter.Empty
    

    as they are equivalent. (As the first one forces the filter condition definitely true, while the second one applies no filter condition).