Search code examples
c#mongodbaggregation-frameworkmongodb-.net-driver

Merge parent field and its nested array field in mongodb


I have a collection like below

{
    "id":"5fd13c33ac0277c435117519",
    "content":"test",
    "votes":[
        {
            "user":"22",
            "isLike":true
        },
        {
            "user":"25",
            "isLike":false
        },
        {
            "user":"43",
            "isLike":false
        }
    ]
},
{
    "id":"5fd13c33ac0277c435237443",
    "content":"test 2",
    "votes":[
        {
            "user":"25",
            "isLike":true
        },
        {
            "user":"43",
            "isLike":false
        }
    ]
}

How can I get the result below with c# driver by querying over votes.user -ie. 25- and then merge those 2 fields from parent and nested array?

{
    "id":"5fd13c33ac0277c435117519",
    "isLike":false
},
{
    "id":"5fd13c33ac0277c435237443",
    "isLike":true
}

EDIT: I've got the result after some try and fails on mongoplayground.net, stil not sure how to convert it over c# driver.

db.collection.aggregate([
  {
    $unwind: "$votes"
  },
  {
    $match: {
      "votes.user": "25"
    }
  },
  {
    $replaceWith: {
      id: "$id",
      isLike: "$votes.isLike"
    }
  }
])

Solution

  • I've managed it like below and wanted to share if someone needs it in the future.

    I personally decided to go one-to-many path with separated vote collection after some readings.

    var match = new BsonDocument("votes.user", 25);
    
    var replace = new BsonDocument(new List<BsonElement> {
        new BsonElement("id", "$id"),
        new BsonElement("isLike", "$votes.isLike"),
    });
    
    return await _collection.Aggregate()
        .Unwind(c => c.votes)
        .Match(match)
        .ReplaceWith<UserVote>(replace)
        .ToListAsync();