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

MongoDB - How to push an embedded array into an existing document


Model:

[BsonIgnoreExtraElements]
public class UserPortfolioList
{
    public string? Username { get; set; }
    public List<Pflist>? Pflist { get; set; }

}

public class Pflist
{
    public string PfName { get; set; } = "DEFAULT NAME";
    public List<string>? Symbols { get; set; }

}

The existing MongoDB Document:

{
  "username": "aaa",
  "pflist": [
    {
      "pfName": "US TECH A",
      "symbols": [
        "GOOG",
        "MSFT"
      ]
    }
  ]
}

The array I want to push (Same username, but different pfName and symbols)

{
  "username": "aaa",
  "pflist": [
    {
      "pfName": "US TECH C",
      "symbols": [
        "AAPL",
        "TSLA"
      ]
    }
  ]
}

Expected result:

{
  "username": "aaa",
  "pflist": [
    {
      "pfName": "US TECH A",
      "symbols": [
        "GOOG",
        "MSFT"
      ]
    },
    {
      "pfName": "US TECH C",
      "symbols": [
        "AAPL",
        "TSLA"
      ]
    }
  ]
}

Code:

public async Task UpdateUserPfAsync(UserPortfolioList userPflist)

  await _UserPortfoliosCollection.UpdateOneAsync(Builders<UserPortfolioList>.Filter.Eq(
    "Username", userPflist.Username),
    Builders<UserPortfolioList>.Update.Push(x => x.Pflist, userPflist.Pflist));

The compiler throws out an error:

can not convert lambda express to type......

I almost tried every approach on the StackOverflow, but none of them works for me.

Please help. Thank you!


Solution

  • Concern:

    Since you are adding a single object to pflist, you should use userPflist.Pflist[0] instead of userPflist.Pflist as with userPflist.Pflist will lead to the result:

    {
      username: "aaa",
      pflist: [
        0: Object
        1: Array
          0: Object
      ]
    }
    

    Push single element to the array

    MongoDB query:

    db.collection.update({
      username: "aaa"
    },
    {
      $push: {
        "pflist": {
          "pfName": "US TECH C",
          "symbols": [
            "AAPL",
            "TSLA"
          ]
        }
      }
    })
    

    Sample Mongo Playground (Push single element to the array)

    MongoDB C#:

    await _UserPortfoliosCollection.UpdateOneAsync(
        Builders<UserPortfolioList>.Filter.Eq("Username", userPflist.Username),
        Builders<UserPortfolioList>.Update.Push(x => x.Pflist, userPflist.Pflist[0]));
    

    Note: The lambda expression for .Push() works if the value is an object instead of an array.


    Push multiple elements to the array

    To push multiple elements into the array, you need a $each operator.

    MongoDB query:

    db.collection.update({
      username: "aaa"
    },
    {
      $push: {
        "pflist": {
          $each: [
            {
              "pfName": "US TECH C",
              "symbols": [
                "AAPL",
                "TSLA"
              ]
            }
          ]
        }
      }
    })
    

    Sample Mongo Playground

    MongoDB C#:

    await _UserPortfoliosCollection.UpdateOneAsync(
        Builders<UserPortfolioList>.Filter.Eq("Username", userPflist.Username),
        Builders<UserPortfolioList>.Update.PushEach(x => x.Pflist, userPflist.Pflist));
    

    Update Result

    enter image description here