C#环境下MongoDB嵌套数组过滤实现方法咨询
在C#中过滤MongoDB嵌套数组的实现方案
需求背景
现有MongoDB文档结构如下:
[ { "Number": "2140007529", "Name": "ABC", "IsInactive": true, "EntryList": [ { "Timestamp": "2022-06-01T14:00:00.000+00:00", "Value": 21564.0 } // 其余条目省略 ] }, { "Number": "2220000784", "Name": "XYZ", "IsInactive": false, "EntryList": [ { "Timestamp": "2022-09-26T13:00:00.000+00:00", "Value": 0.0 }, { "Timestamp": "2023-01-01T11:54:00.000+00:00", "Value": 528.56 } // 其余条目省略 ] } ]
需要实现两个筛选逻辑:
- 仅保留
IsInactive为false的文档 - 对符合条件的文档,仅返回
EntryList中Timestamp大于2022-12-31的条目
实现步骤
1. 定义C#实体模型
先对应MongoDB文档结构创建强类型模型:
public class Entry { public DateTime Timestamp { get; set; } public double Value { get; set; } } public class Device { public string Number { get; set; } public string Name { get; set; } public bool IsInactive { get; set; } public List<Entry> EntryList { get; set; } }
2. 聚合管道实现(贴近MongoDB原生语法)
这种方式和你在MongoDB Compass中使用的聚合逻辑完全对应:
using MongoDB.Driver; using MongoDB.Bson; using System; using System.Threading.Tasks; // 初始化Mongo客户端和集合 var mongoClient = new MongoClient("mongodb://localhost:27017"); var db = mongoClient.GetDatabase("你的数据库名"); var collection = db.GetCollection<Device>("你的集合名"); // 定义时间阈值(使用UTC时间,和文档中的Timestamp格式匹配) var cutoffDate = new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc); // 构建聚合管道 var pipeline = new BsonDocument[] { // 第一步:匹配IsInactive为false的文档 new BsonDocument("$match", new BsonDocument("IsInactive", false)), // 第二步:过滤EntryList数组,保留符合时间条件的元素 new BsonDocument("$addFields", new BsonDocument( "EntryList", new BsonDocument("$filter", new BsonDocument { { "input", "$EntryList" }, { "cond", new BsonDocument("$gt", new BsonArray { "$$this.Timestamp", cutoffDate }) } }) )) }; // 执行聚合查询 var result = await collection.Aggregate<Device>(pipeline).FirstOrDefaultAsync();
3. LINQ方式实现(更符合C#习惯)
如果偏好LINQ语法,可以用更直观的写法:
using MongoDB.Driver; using System; using System.Threading.Tasks; // 初始化客户端和集合(同上) var mongoClient = new MongoClient("mongodb://localhost:27017"); var db = mongoClient.GetDatabase("你的数据库名"); var collection = db.GetCollection<Device>("你的集合名"); var cutoffDate = new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc); // 用LINQ构建查询 var result = await collection.Aggregate() .Match(device => !device.IsInactive) .Project(device => new Device { Number = device.Number, Name = device.Name, IsInactive = device.IsInactive, EntryList = device.EntryList.Where(entry => entry.Timestamp > cutoffDate).ToList() }) .FirstOrDefaultAsync();
注意事项
- 确保时间类型的一致性:文档中的
Timestamp是UTC格式,C#中必须使用DateTimeKind.Utc的时间实例,避免时区差异导致过滤结果错误。 - 如果需要排除过滤后
EntryList为空的文档,可以在聚合管道中添加额外的$match阶段:new BsonDocument("$match", new BsonDocument("EntryList", new BsonDocument("$ne", new BsonArray())))
内容的提问来源于stack exchange,提问作者huckler
相关产品推荐
相关产品推荐

