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