MongoDB C#驱动:查询UserThemes中值大于100的用户
问题:筛选UserThemes中存在值大于100的用户
需求说明
我有一个UserInfo集合,其中包含UserThemes字段(类型为BsonDocument),需要筛选出UserThemes中至少有一个值大于100的用户。
C#实体定义
public record UserInfo:BaseDocument { public string UserName { get; set; } public BsonDocument UserThemes { get; init; } = new BsonDocument(); }
示例存储数据
{ "_id" : ObjectId("62f8fe33127584b3e027060e"), "UserId" : "7BCBCC2DA9624BCB8191AC2DBDC5CA71", "UserName" : "kaveh", "UserThemes" : { "football" : 10, "basketball" : 110, "volleyball" : 90, "tennis" : 50, "golf" : 25 } }
失败的尝试代码
var docs = await _context.UserInfos.Aggregate() .Match( new BsonDocument() { { "$expr", new BsonDocument() { { "$and", new BsonArray() { new BsonDocument(){{ "$gt", new BsonArray() { "$UserThemes.value", BsonValue.Create(100) } } }, } } } } }) .As<UserInfo>() .ToListAsync();
问题分析
之前的写法错误在于$UserThemes.value的引用方式不成立——UserThemes是嵌套文档而非数组,无法直接通过.value提取所有值。必须先将文档的键值对转换为数组,再判断其中是否存在满足条件的元素。
正确解决方案
方案一:聚合表达式实现(推荐)
通过$objectToArray把UserThemes转为键值对数组,再用$filter筛选出值大于100的元素,最后判断筛选结果的长度是否大于0:
var docs = await _context.UserInfos.Aggregate() .Match(new BsonDocument { { "$expr", new BsonDocument { { "$gt", new BsonArray { new BsonDocument { { "$size", new BsonDocument { { "$filter", new BsonDocument { { "input", new BsonDocument("$objectToArray", "$UserThemes") }, { "cond", new BsonDocument("$gt", new BsonArray { "$$this.v", 100 }) } } } } }, 0 } } } } } }) .As<UserInfo>() .ToListAsync();
方案二:简化聚合写法
用$anyElementTrue结合$map遍历数组,直接判断是否存在满足条件的元素:
var docs = await _context.UserInfos.Aggregate() .Match(new BsonDocument { { "$expr", new BsonDocument { { "$anyElementTrue", new BsonDocument { { "$map", new BsonDocument { { "input", new BsonDocument("$objectToArray", "$UserThemes") }, { "in", new BsonDocument("$gt", new BsonArray { "$$this.v", 100 }) } } } } } } } }) .As<UserInfo>() .ToListAsync();
方案三:LINQ表达式写法(更符合C#习惯)
如果习惯用LINQ,新版本MongoDB Driver(2.x及以上)支持直接解析LINQ表达式:
var docs = await _context.UserInfos.Aggregate() .Match(u => u.UserThemes.Values.Any(v => v.AsInt32 > 100)) .As<UserInfo>() .ToListAsync();
内容的提问来源于stack exchange,提问作者Kaveh Naseri
相关产品推荐
相关产品推荐

