C#操作MongoDB如何查询嵌套数组与指定ID集合存在交集的文档
实现前提
首先确认你已定义对应数据模型,示例参考如下:
// 根文档模型,对应MongoDB集合存储结构 public class RootDocument { public ObjectId Id { get; set; } public List<ObjectItem> objects { get; set; } } public class ObjectItem { public int id { get; set; } public List<TrackingData> tracking_datas { get; set; } } public class TrackingData { public int id { get; set; } public List<int> polygons { get; set; } }
实现代码(C# MongoDB 驱动)
这里提供两种可直接使用的写法,适配不同驱动版本:
写法1:强类型表达式写法(推荐,驱动v2.14+支持)
// 注入/获取MongoDB集合实例 var mongoCollection = mongoDatabase.GetCollection<RootDocument>("你的集合名"); // 你的参考条件数组 var requiredPolygons = new List<int> { 1, 2 }; // 1. 匹配条件:筛选出至少有一个符合要求的tracking_datas的文档 var matchFilter = Builders<RootDocument>.Filter .ElemMatch(root => root.objects, obj => obj.tracking_datas.Any(td => td.polygons.Any(p => requiredPolygons.Contains(p)))); // 2. 投影过滤:仅保留tracking_datas中符合条件的子项 var projection = Builders<RootDocument>.Projection.Expression(root => new RootDocument { Id = root.Id, objects = root.objects.Select(obj => new ObjectItem { id = obj.id, // 过滤不符合条件的tracking_datas子项 tracking_datas = obj.tracking_datas .Where(td => td.polygons.Intersect(requiredPolygons).Any()) .ToList() }) // 如果需要过滤掉tracking_datas为空的object,可打开下面的注释 // .Where(obj => obj.tracking_datas.Any()) .ToList() }); // 执行查询 var result = await mongoCollection.Find(matchFilter) .Project(projection) .ToListAsync();
写法2:Bson原生聚合写法(兼容所有驱动版本)
如果旧版本驱动无法解析Linq表达式,用原生聚合管道实现:
var mongoCollection = mongoDatabase.GetCollection<RootDocument>("你的集合名"); var requiredPolygons = new List<int> { 1, 2 }; var requiredBsonArray = new BsonArray(requiredPolygons); var pipeline = new BsonDocumentStagePipelineDefinition<RootDocument, RootDocument>( new List<BsonDocument> { // 匹配阶段 new BsonDocument("$match", new BsonDocument { { "objects.tracking_datas.polygons", new BsonDocument("$in", requiredBsonArray) } }), // 投影过滤阶段 new BsonDocument("$project", new BsonDocument { { "_id", 1 }, { "objects", new BsonDocument("$map", new BsonDocument { { "input", "$objects" }, { "as", "obj" }, { "in", new BsonDocument { { "id", "$$obj.id" }, { "tracking_datas", new BsonDocument("$filter", new BsonDocument { { "input", "$$obj.tracking_datas" }, { "as", "td" }, // 判断两个数组是否有交集 { "cond", new BsonDocument("$gt", new BsonArray { new BsonDocument("$size", new BsonDocument("$setIntersection", new BsonArray { "$$td.polygons", requiredBsonArray })), 0 }) } }) } } } }) } }) }); var result = await mongoCollection.Aggregate(pipeline).ToListAsync();
优化提示
- 建议给
objects.tracking_datas.polygons字段添加索引,大幅提升大数量级下的查询效率 - 如果你的集合直接存储
ObjectItem列表(最外层没有objects数组),只需去掉代码中对应objects层级的操作即可
内容的提问来源于stack exchange,提问作者Mehmet Serkan Ekinci
相关产品推荐
相关产品推荐

