如何使用C#控制MongoDB的Projection实现字典字段键过滤
结论
该需求完全可实现,你最后尝试的Expression类型投影思路是正确的,报错是因为低版本MongoDB C#驱动暂不支持直接解析Dictionary键过滤的LINQ表达式,替换为兼容的投影写法即可。
正确实现方案
写法1:原生Bson操作投影(全版本兼容)
利用MongoDB的三个原生操作符实现字典过滤:
$objectToArray:将BSON对象(即你的Dictionary字段)转换为[{k:"键",v:"值"}]格式的数组$filter:过滤数组中键满足前缀匹配要求的条目$arrayToObject:将过滤后的数组转回BSON对象,映射回C#的Dictionary类型
代码如下:
// 定义投影 ProjectionDefinition<Thing> projection = new BsonDocument { { nameof(Thing.Id), 1 }, { nameof(Thing.Name), 1 }, { nameof(Thing.Stuff), new BsonDocument("$arrayToObject", new BsonDocument("$filter", new BsonDocument { { "input", new BsonDocument("$objectToArray", "$Stuff") }, { "cond", new BsonDocument("$regexMatch", new BsonDocument { { "input", "$$this.k" }, { "regex", "^duck" } // 匹配以duck开头的键 }) } }) )} }; // 查询调用 Thing result = await _dbContext.Things .Find(x => x.Name == name) .Project<Thing>(projection) .SingleOrDefaultAsync(token);
写法2:强类型LINQ表达式投影(驱动版本≥2.19支持)
如果你使用的MongoDB C#驱动版本在2.19及以上,调整你最后写的表达式即可直接运行:
ProjectionDefinition<Thing, Thing> projection = Builders<Thing>.Projection .Expression(a => new Thing { Id = a.Id, Name = a.Name, Stuff = a.Stuff .Where(kv => kv.Key.StartsWith("duck")) .ToDictionary(kv => kv.Key, kv => kv.Value) }); // 查询调用和上面一致 Thing result = await _dbContext.Things .Find(x => x.Name == name) .Project<Thing>(projection) .SingleOrDefaultAsync(token);
可参考的搜索关键词
- MongoDB C#驱动 条件投影 Dictionary过滤
- MongoDB $objectToArray $filter 嵌套对象过滤
- MongoDB 投影 过滤对象键
内容的提问来源于stack exchange,提问作者Konrad Viltersten
相关产品推荐
相关产品推荐

