如何在Mongoose中返回符合条件的嵌套数组匹配元素?
MongoDB 查询:按指定code过滤数组元素并保留文档结构
原始文档
{ "_id": "63aadd124fabe6c7f5cb3af5", "url": "https://github.com", "sender": "username@gmail.com", "recipients": [ { "email": "recipient1@gmail.com", "code": "XY231", "position": 54 }, { "email": "recipient1@gmail.com", "code": "XY231", "position": 48 }, { "email": "recipient2@gmail.com", "code": "AB124", "position": 114 } ], "properties": [ { "page": 0, "recipient": { "email": "recipient1@gmail.com", "code": "XY231" } }, { "page": 2, "recipient": { "email": "recipient2@gmail.com", "code": "AB124" } } ], "createdAt": "2023-01-11T16:02:56.126Z", "updatedAt": "2023-01-14T09:49:41.962Z", "__v": 0 }
查询需求
基于 recipients.code: XY231 过滤文档,要求:
- 保留原文档整体结构
recipients数组仅保留匹配code: XY231的元素properties数组仅保留其嵌套recipient.code为XY231的元素- 若
recipients无匹配元素,返回空数组或null
预期返回结果:
{ "_id": "63aadd124fabe6c7f5cb3af5", "url": "https://github.com", "sender": "username@gmail.com", "recipients": [ { "email": "recipient1@gmail.com", "code": "XY231", "position": 54 }, { "email": "recipient1@gmail.com", "code": "XY231", "position": 48 } ], "properties": [ { "page": 0, "recipient": { "email": "recipient1@gmail.com", "code": "XY231" } } ], "createdAt": "2023-01-11T16:02:56.126Z", "updatedAt": "2023-01-14T09:49:41.962Z", "__v": 0 }
尝试过的方法及问题
使用 $unwind 和 $project 组合查询,但仅返回单个匹配元素,文档结构被破坏,返回结果如下:
{ "_id": "63aadd124fabe6c7f5cb3af5", "url": "https://github.com", "sender": "username@gmail.com", "recipients": { "email": "recipient1@gmail.com", "code": "XY231" }, "properties": { "page": 0, "recipient": { "email": "recipient1@gmail.com", "code": "XY231" }, { "email": "recipient1@gmail.com", "code": "XY231" } }, "createdAt": "2023-01-11T16:02:56.126Z", "updatedAt": "2023-01-14T09:49:41.962Z", "__v": 0 }
解决方案
使用 MongoDB 聚合框架的 $match + $project + $filter 组合实现需求:
db.collection.aggregate([ // 先筛选包含目标code的文档,减少后续处理量 { $match: { "recipients.code": "XY231" } }, // 过滤数组元素并保留原文档字段 { $project: { url: 1, sender: 1, createdAt: 1, updatedAt: 1, __v: 1, // 过滤recipients数组,保留code匹配的元素 recipients: { $filter: { input: "$recipients", cond: { $eq: ["$$this.code", "XY231"] } } }, // 过滤properties数组,保留嵌套recipient.code匹配的元素 properties: { $filter: { input: "$properties", cond: { $eq: ["$$this.recipient.code", "XY231"] } } } } }, // 可选:排除过滤后recipients为空的文档,不需要可删除此阶段 { $match: { $expr: { $ne: ["$recipients", []] } } } ])
说明
$match阶段先筛选出符合条件的文档,避免对无关文档进行处理$filter操作符精准过滤数组元素,保留原数组结构,不会像$unwind那样展开数组- 最后一个
$match用于过滤掉无匹配元素的文档,若需保留这类文档(返回空数组)可直接移除该阶段
内容的提问来源于stack exchange,提问作者Saquib Nasim
相关产品推荐
相关产品推荐

