How to partial update mongodb document in Web Api Patch request

526 Views Asked by At

I want to partial update fileds of my document that changed in the patch request and in every request the field probably changed for example one time Balance will be charged another time AccountHolder and others. I want to update each specific field in single method not create a method for the number of fields .

Note: there is nothing in IDto interface, I use it just for separating Dtos from other classes.

UpdateAccountDto.cs

public class UpdateAccountDto : IDto
{
    public string Id { get; set; } = string.Empty;
    public string AccountId { get; set; } = string.Empty;

    public string AccountHolder { get; set; } = string.Empty;

    public string AccountType { get; set; } = string.Empty;

    public decimal Balance { get; set; }
}

Account.cs my entity

public class Account
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; } = string.Empty;
    [BsonElement("account_id")] 
    public string AccountId { get; set; } = string.Empty;

    [BsonElement("account_holder")]
    public string AccountHolder { get; set; } = string.Empty;

    [BsonElement("account_type")]
    public string AccountType { get; set; } = string.Empty;
    
    [BsonRepresentation(BsonType.Decimal128)]
    [BsonElement("balance")]
    public decimal Balance { get; set; }

}

My endpoint

        [HttpPatch("UpdatePartialAccount")]
        public async Task<ActionResult> UpdatePartialAccount([FromQuery]string id,[FromBody] JsonPatchDocument<UpdateAccountDto>? document)
        {
            if (document is null)
                return BadRequest();

            var updateAccountDto = document.ToDto();

            document.ApplyTo(updateAccountDto, ModelState);

            if (!ModelState.IsValid)
                return BadRequest();

            var entity = updateAccountDto.ToEntity<Account>();
            entity.Id = id;

            await _accountRepository.PartialUpdateAsync(entity);

            return NoContent();

        }

PartialUpdateAsync method

   public async Task<UpdateResult> PartialUpdateAsync(Account account)
    {
        //var filter = Builders<Account>.Filter.Eq(a => a.Id, account.Id);
        //var update = Builders<Account>.Update.Set()
        //Partial update

        
    }
1

There are 1 best solutions below

2
Chen On

Your question are actually not very clear, but I guess you may want to know the field settings corresponding to JsonPatchDocument and the operation of updating the Mongodb database.

Regarding the field setting of JsonPatchDocument, you can refer to the official document to use it. For example:

[HttpPatch("UpdatePartialAccount")]
        public async Task<ActionResult> UpdatePartialAccount([FromQuery] string id, [FromBody] JsonPatchDocument<UpdateAccountDto>? document)
{
    if (document is null)
        return BadRequest();

    var dto = new UpdateAccountDto() { AccountId = "DAccount1" };

    document.ApplyTo(dto, ModelState);
    //.....
}

Suppose you do a Replace operation on it:

[
  {
    "operationType": 2,
    "path": "/accountHolder",
    "op": "replace",
    "value": "TestHolder"
  }
]

At this point your dto will become:

enter image description here

Please confirm the content of dto and then match with Account to update the database(I'm not sure how you map to Account, but I used AutoMapper). For example:

public async Task UpdateAsync(Account account)
{
    await _account.UpdateOneAsync(c => c.AccountId == account.AccountId, account.AccountHolder);
}

For more operations on updating the database, you can check this link.

Hope this can help you.