使用 MongoDB 和 C# 查询数组中深度嵌套的对象

Query a deeply nested object in arrays using MongoDB and C#

我是 MongoDB 的新手,我已经面临着汗流浃背的挑战。我试图从一个数组中获取一个元素,该数组中的对象位于一个包含对象的数组中(如果这有意义的话)。这是文档的样子以及我想要获得的内容:

所以基本上结构如下:

为了获得我匹配的 OptionMenuItem,使用来自 MongoDB Compass 工具

的聚合管道工具将其拉下来
[{
    $unwind: {
        path: '$subjects'
    }
}, {
    $unwind: {
        path: '$subjects.items'
    }
}, {
    $project: {
        _id: '$subjects.items._id',
        item: '$subjects.items'
    }
}, {
    $match: {
        _id: ObjectId('5e6eaef8ae35a418f4f6dbd4')
    }
}]

然后我尝试将其翻译成 C# 但没有成功,这是我目前为止的情况:

        var optionMenuItem = await collection.Aggregate()
           .Unwind<OptionMenu, OptionMenuSubject>(i => i.Subjects)
           .Unwind<OptionMenuSubject, OptionMenuItem>(i => i.Items)
           .Match(i => i.Id == id)
           .ToListAsync();

如果有人知道我做错了什么或者我该如何解决这个问题,将不胜感激:)

展开未过滤的数据不是一个好主意,因为它会在 mongodb 内存中创建大量数据,您可能会达到 100mb 的聚合管道限制。因此,在展开之前,请尝试始终过滤和缩小记录范围。我相信以下管道会提供您需要的结果:

db.collection.aggregate([
    {
        $match: {
            'subjects.items._id': ObjectId('5e6eaef8ae35a418f4f6dbd4')
        }
    },
    {
        $unwind: '$subjects'
    },
    {
        $unwind: '$subjects.items'
    },
    {
        $match: {
            'subjects.items._id': ObjectId('5e6eaef8ae35a418f4f6dbd4')
        }
    },
    {
        $replaceWith: '$subjects.items'
    }
])

这里是 convenient way to execute this pipeline with c#. you can read more about how it works here

最后我就是这样解决的。这不是我最引以为豪的作品,因为它没有强大的输入功能,但它确实有效:

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();