Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I flatten this array of subdocuments?

This is the query I want to execute in my C# code:

db.Courses.aggregate([
  {$unwind: "$topics"},
  {$project: {"topics":1, _id:0}},
  {$replaceRoot:{newRoot:"$topics"}}
])

This gives me this output when I execute it in MongoDB shell:

{ _id: null,
  title: 'My Topic',
  description: 'My Topic Desc',
  lessons: 
   [ { lessonId: 'Lessonid1',
       title: 'My Lesson',
       description: 'My Lesson Desc' } ] }

Which is exactly what I want. My attempt at translating this into C# is:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

var topics = await collection.Aggregate()
    .Unwind<Course>(c=>c.Topics)
    .Project("topics")
    .ReplaceRoot<Topic>(newRoot:"$topics")
    .ToListAsync();

Unfortunately, this doesn’t work and I get this error:

System.FormatException: JSON reader was expecting a value but found ‘topics’.

For reference here is my C# class structure:

public class Course
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string? CourseId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public List<Topic>? Topics { get; set; }
}

public class Topic
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string? TopicId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }

    public List<LessonSummary>? Lessons { get; set; }

}

public class LessonSummary
{
    public string LessonId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
}

And this is the full data in the collection I’m using:

[
  {
    "courseId": "624487662a2b383f7306c5ad",
    "title": "My Course",
    "description": "My Course Desc",
    "topics": [
      {
        "topicId": null,
        "title": "My Topic",
        "description": "My Topic Desc",
        "lessons": [
          {
            "lessonId": "Lessonid1",
            "title": "My Lesson",
            "description": "My Lesson Desc"
          }
        ]
      }
    ]
  }
]

What am I doing wrong in the C# code that’s different from the MongoDB shell?

>Solution :

I think $project stage can be skipped from your scenario.

db.Courses.aggregate([
  {$unwind: "$topics"},
  {$replaceRoot:{newRoot:"$topics"}}
])
var topics = await collection.Aggregate()
    .Unwind<Course>(c=>c.Topics)
    .ReplaceRoot<Topic>(newRoot:"$topics")
    .ToListAsync();

If you need $project stage, you can pass the BsonDocument as

.Project("{ topics: 1, _id: 0 }")

OR

.Project(new BsonDocument { { "topics", 1 }, { "_id", 0 } })
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading