如何在ExpressJS和MongoDB中过滤对象的子属性值?
如何在ExpressJS+MongoDB中过滤数组字段的子文档
需求:从MongoDB获取某代理的全部数据,仅保留testimonials数组中isDisplayed为true的条目。
原尝试代码
const getSingleAgent = expressAsync(async (req, res) => { const agent = await Agents.findOne({ _id: req.params.id, }); res.json(agent); } else { res.status(404); throw new Error("Agent not found."); } });
实际返回结果
{ "_id": "63ea901a85d4fbd62fb887b3", "name": "test namee", "isDeclined": false, "testimonials": [ { "isDisplayed": true, "name": "test123123123123123", }, { "isDisplayed": false, "name": "test123123123123123", }, { "isDisplayed": false, "name": "test@gmail.com", }, ], }
期望返回结果
{ "_id": "63ea901a85d4fbd62fb887b3", "name": "test namee", "isDeclined": false, "testimonials": [ { "isDisplayed": true, "name": "test123123123123123", }, ], }
解决方案
方案1:MongoDB查询阶段过滤(推荐)
直接在数据库层面过滤数组,减少传输到服务器的数据量,适合大数据场景。可以用$filter操作符结合聚合管道或find的投影参数实现:
方式1:使用聚合管道
const getSingleAgent = expressAsync(async (req, res) => { const agent = await Agents.aggregate([ // 匹配目标代理 { $match: { _id: req.params.id } }, // 投影并过滤testimonials数组 { $project: { name: 1, isDeclined: 1, testimonials: { $filter: { input: "$testimonials", cond: { $eq: ["$$this.isDisplayed", true] } } } } } ]).then(result => result[0]); // 聚合返回数组,取第一个元素 if (agent) { res.json(agent); } else { res.status(404); throw new Error("Agent not found."); } });
方式2:使用find的投影参数(MongoDB 3.2+支持)
const getSingleAgent = expressAsync(async (req, res) => { const agent = await Agents.findOne( { _id: req.params.id }, { name: 1, isDeclined: 1, testimonials: { $filter: { input: "$testimonials", cond: { $eq: ["$$this.isDisplayed", true] } } } } ); if (agent) { res.json(agent); } else { res.status(404); throw new Error("Agent not found."); } });
方案2:Node.js层面过滤(简单直接)
如果数据量不大,也可以在获取完整数据后,用数组的filter方法过滤:
const getSingleAgent = expressAsync(async (req, res) => { let agent = await Agents.findOne({ _id: req.params.id }); if (agent) { // 过滤testimonials中isDisplayed为true的条目 agent.testimonials = agent.testimonials.filter(item => item.isDisplayed === true); res.json(agent); } else { res.status(404); throw new Error("Agent not found."); } });
内容的提问来源于stack exchange,提问作者Dave Spencer Bacay
相关产品推荐
相关产品推荐

