Reputation: 85
I'm pretty new to MongoDB and already I face a sweaty challenge. I'm trying to get an element from an array with objects inside of an array with objects (if that makes sense). This is how a document looks like and what I am trying to get:
So basically the structure is as follows:
To get the OptionMenuItem I matched to pull it off using the aggregation pipeline tool from MongoDB Compass tool
[{
$unwind: {
path: '$subjects'
}
}, {
$unwind: {
path: '$subjects.items'
}
}, {
$project: {
_id: '$subjects.items._id',
item: '$subjects.items'
}
}, {
$match: {
_id: ObjectId('5e6eaef8ae35a418f4f6dbd4')
}
}]
Then I tried translating this to C# with no success, this is as far as I've come:
var optionMenuItem = await collection.Aggregate()
.Unwind<OptionMenu, OptionMenuSubject>(i => i.Subjects)
.Unwind<OptionMenuSubject, OptionMenuItem>(i => i.Items)
.Match(i => i.Id == id)
.ToListAsync();
If somebody knows what I'm doing wrong or how I can pull this off it would be very much appreciated :)
Upvotes: 2
Views: 1659
Reputation: 85
This is how I eventually solved it. Not my proudest work because it doesn't have the strong typing in it, but it works:
var collection = Database.GetCollection<BsonDocument>(_collectionName);
var query = await collection.Aggregate()
.Match(i => i["subjects.items._id"] == ObjectId.Parse(id))
.Unwind(i => i["subjects"])
.Unwind(i => i["subjects.items"])
.Match(i => i["subjects.items._id"] == ObjectId.Parse(id))
.ReplaceRoot(i => i["subjects.items"])
.FirstOrDefaultAsync();
Upvotes: 1
Reputation: 5669
unwinding unfiltered data is not a good idea because it creates a lot of data in mongodb memory and you might reach the 100mb aggregation pipeline limit. so try to always filter and narrow down records before unwinding. i believe the following pipeline would give the result you need:
db.collection.aggregate([
{
$match: {
'subjects.items._id': ObjectId('5e6eaef8ae35a418f4f6dbd4')
}
},
{
$unwind: '$subjects'
},
{
$unwind: '$subjects.items'
},
{
$match: {
'subjects.items._id': ObjectId('5e6eaef8ae35a418f4f6dbd4')
}
},
{
$replaceWith: '$subjects.items'
}
])
here's a convenient way to execute this pipeline with c#. you can read more about how it works here.
Upvotes: 0