Home > Mobile >  How can I flatten this array of subdocuments?
How can I flatten this array of subdocuments?

Time:03-31

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:

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?

CodePudding user response:

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 } })
  • Related