MongoDB查询如何仅返回文档中schools数组内匹配条件的对象
问题原因
你当前使用的$elemMatch是查询操作符,作用是筛选出「schools数组中至少存在一个符合条件元素的文档」,不会过滤数组内部返回的内容,所以会返回完整的原文档。要实现数组元素过滤,需要搭配投影操作或者聚合管道。
第一种需求:保留原文档其他字段,仅过滤schools数组
方案1:仅返回第一个匹配元素(适用于数组最多一个匹配的场景)
直接在find查询的投影参数中使用投影版的$elemMatch,Go代码示例:
// 筛选符合条件的文档 filter := bson.M{"schools.name": "howard"} // 配置投影,保留原有字段+过滤schools数组 opts := options.Find().SetProjection(bson.M{ "id": 1, "description": 1, "schools": bson.M{"$elemMatch": bson.M{"name": "howard"}}, }) // 执行查询 cursor, err := collection.Find(ctx, filter, opts)
方案2:返回所有匹配的数组元素(适用于数组有多个匹配的场景)
使用聚合管道的$filter操作符实现全匹配过滤:
pipeline := mongo.Pipeline{ // 第一步:筛选符合条件的文档 bson.D{{"$match", bson.D{{"schools.name", "howard"}}}}, // 第二步:过滤schools数组,保留所有匹配元素,其他字段保持不变 bson.D{{"$addFields", bson.D{ {"schools", bson.D{{"$filter", bson.D{ {"input", "$schools"}, {"cond", bson.D{{"$eq", bson.A{"$$this.name", "howard"}}}}, }}}}, }}}, } // 执行聚合查询 cursor, err := collection.Aggregate(ctx, pipeline)
第二种需求:仅返回包含匹配元素的schools数组
在上述方案的基础上调整投影配置即可:
对应方案1(仅返回第一个匹配元素)
filter := bson.M{"schools.name": "howard"} // 投影仅保留schools字段,隐藏其他字段 opts := options.Find().SetProjection(bson.M{ "_id": 0, // 不需要默认_id字段可加这行 "schools": bson.M{"$elemMatch": bson.M{"name": "howard"}}, }) cursor, err := collection.Find(ctx, filter, opts)
对应方案2(返回所有匹配元素)
在聚合管道末尾新增$project阶段:
pipeline := mongo.Pipeline{ bson.D{{"$match", bson.D{{"schools.name", "howard"}}}}, bson.D{{"$addFields", bson.D{ {"schools", bson.D{{"$filter", bson.D{ {"input", "$schools"}, {"cond", bson.D{{"$eq", bson.A{"$$this.name", "howard"}}}}, }}}}, }}}, // 新增阶段:仅保留schools字段 bson.D{{"$project", bson.D{ {"_id", 0}, {"schools", 1}, }}}, } cursor, err := collection.Aggregate(ctx, pipeline)
内容的提问来源于stack exchange,提问作者shekwo
相关产品推荐
相关产品推荐

