C# MongoDB查询:获取文档及匹配指定用户的数组元素问题
解决MongoDB查询中返回数组所有匹配元素的问题
我懂你现在的困扰啦——你想获取完整的Blends根文档,同时只保留Review数组里匹配指定用户的所有评论,但当前代码只能返回第一个匹配的评论,对吧?
问题根源
你当前使用的Review.$是MongoDB的位置操作符,它的核心作用就是仅返回数组中第一个匹配查询条件的元素,这就是为什么你只能拿到一条评论的原因。要返回所有匹配的数组元素,我们需要用更灵活的数组过滤方式。
解决方案一:使用聚合管道(推荐)
通过MongoDB的聚合管道,我们可以先筛选出符合条件的文档,再过滤数组保留所有匹配的元素,同时完整保留根文档的其他字段:
var client = new MongoClient(connectionString); IMongoDatabase db = client.GetDatabase("GinAndTonic"); var collection = db.GetCollection<Blends>("Blends"); var targetUsername = "你要查询的用户名"; var aggregationPipeline = new BsonDocument[] { // 第一步:筛选出包含目标用户评论的Blends文档 new BsonDocument("$match", new BsonDocument("Review.User", targetUsername)), // 第二步:替换Review字段为过滤后的数组,只保留目标用户的评论 new BsonDocument("$addFields", new BsonDocument( "Review", new BsonDocument("$filter", new BsonDocument { {"input", "$Review"}, {"as", "review"}, {"cond", new BsonDocument("$eq", new BsonArray {"$$review.User", targetUsername})} }) )) }; var result = await collection.Aggregate<Blends>(aggregationPipeline).ToListAsync();
解决方案二:使用LINQ投影(更易读)
如果你习惯用LINQ语法,MongoDB驱动可以自动将LINQ的数组过滤逻辑转换成MongoDB的$filter操作符,代码更直观:
var client = new MongoClient(connectionString); IMongoDatabase db = client.GetDatabase("GinAndTonic"); var collection = db.GetCollection<Blends>("Blends"); var targetUsername = "你要查询的用户名"; // 先筛选出包含目标用户评论的文档 var filter = Builders<Blends>.Filter.Eq("Review.User", targetUsername); // 构建投影:保留所有根文档字段,同时过滤Review数组 var projection = Builders<Blends>.Projection.Expression(blend => new Blends { _id = blend._id, GinID = blend.GinID, TonicID = blend.TonicID, GarnishID = blend.GarnishID, GinName = blend.GinName, TonicName = blend.TonicName, GarnishName = blend.GarnishName, Rating = blend.Rating, RatingSum = blend.RatingSum, RatingCount = blend.RatingCount, Review = blend.Review.Where(review => review.User == targetUsername).ToList() }); var result = await collection.Find(filter).Project(projection).ToListAsync();
补充说明
- 这两种方法都要求你的MongoDB版本在3.2及以上(
$filter操作符从3.2开始支持),现在大部分生产环境都满足这个条件。 - 如果你的MongoDB版本过低,只能用
$unwind+$match+$group的组合方式,但这种方式代码更繁琐,性能也不如$filter,不推荐。
内容的提问来源于stack exchange,提问作者Saintz
相关产品推荐
相关产品推荐

