Search code examples
c#mongodbmongodb-queryaggregation-frameworkmongodb-.net-driver

How to fetch collection of subdocument using mongodb C# driver?


I have following MongoDB document:

{
  "_id": {
    "$oid": "5fbfa0005c15aaf2eac69ba6"
  },
  "PostMedia": [
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img1.jpg",
      "Title": null,
      "Description": ""
    },
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img2.jpg",
      "Title": null,
      "Description": ""
    }
  ]
},
{
  "_id": {
    "$oid": "5fbfa0485c15aaf2eac69ba7"
  },
  "PostMedia": [
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img3.jpg",
      "Title": null,
      "Description": ""
    },
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img4.jpg",
      "Title": null,
      "Description": ""
    }
  ]
}

and I want to fetch all PostMedia to single array using MongoDB C# driver. Here is the expected result:

[
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img1.jpg",
      "Title": null,
      "Description": ""
    },
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img2.jpg",
      "Title": null,
      "Description": ""
    }, {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img3.jpg",
      "Title": null,
      "Description": ""
    },
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img4.jpg",
      "Title": null,
      "Description": ""
    }
  ]

I had tried to use group aggregation function but it returned an array of array.

enter image description here

Result I received:

PostMedia:[{
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img1.jpg",
      "Title": null,
      "Description": ""
    },
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img2.jpg",
      "Title": null,
      "Description": ""
    }],[
     {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img3.jpg",
      "Title": null,
      "Description": ""
    },
    {
      "FilePath": "http://localhost:8886/localhost44323/image/",
      "Filename": "img4.jpg",
      "Title": null,
      "Description": ""
    }
  ]

C# code I have written so far is as follows:

  var group = new[]
                {
                new BsonDocument("$group",
                new BsonDocument
                {
                    { "_id", BsonNull.Value },
                    { "PostMedia", new BsonDocument("$push", "$PostMedia") }
                })
            };
                var result = collection.Aggregate<MediaList>(group).FirstOrDefault();
                return list;
            }

Is there any way to fetch subdocument by merging them is a single array.


Solution

  • You have to $unwind before $group,

    • $unwind deconstruct PostMedia array
    • $replaceRoot replace PostMedia object to root
    • $unset remove _id field
      { $unwind: "$PostMedia" },
      {
        $group: {
          _id: null,
          PostMedia: { $push: "$PostMedia" }
        }
      },
      { $unset: "_id" } // remove field
    

    Playground

    C#:

    new BsonArray
    {
        new BsonDocument("$unwind", "$PostMedia"),
        new BsonDocument("$group", 
        new BsonDocument
            {
                { "_id", BsonNull.Value }, 
                { "PostMedia", 
        new BsonDocument("$push", "$PostMedia") }
            })
        new BsonDocument("$unset", "_id")
    }