mongoose(MongoDB)使用find查询嵌套对象isDraft筛选不生效求助
问题原因
MongoDB的find查询默认只会筛选符合条件的文档本身,不会自动过滤文档内部的数组成员。你当前的查询逻辑只是筛选出「createdBy匹配、且version数组中至少存在一个isDraft为true的合同文档」,返回结果会保留完整的合同文档,因此version数组会包含所有元素。
解决方案
方案1:使用find投影参数过滤数组(简单场景适用)
如果每个合同最多只有一个isDraft为true的version,可以用$elemMatch投影操作符只返回第一个匹配的数组成员:
const query = { createdBy: clientAdminDetails._id, "version.isDraft": true // 多条件默认就是与关系,不需要额外加$and }; await Contract .find(query, { // 声明需要返回的字段,version只返回匹配isDraft=true的元素 version: { $elemMatch: { isDraft: true } }, name: 1, createdBy: 1, __v: 1 }) .skip(req.body.noOfItems * (req.body.pageNumber - 1)) .limit(req.body.noOfItems) .exec((err, contract) => { // 后续原有逻辑保持不变 if (err) { return res.json(err); } Contract.countDocuments(query).exec((count_error, count) => { if (err) { return res.json(count_error); } return res.json({ total: count, page: req.body.pageNumber, pageSize: contract.length, contracts: contract }); }); });
注意:$elemMatch只会返回数组中第一个匹配的元素,如果一个合同存在多个isDraft为true的version,需要使用方案2。
方案2:使用聚合管道(支持多匹配元素、更灵活)
如果需要返回所有isDraft为true的version元素,可以用聚合管道的$filter操作实现数组过滤:
const query = { createdBy: clientAdminDetails._id, "version.isDraft": true }; await Contract.aggregate([ // 第一步匹配符合条件的合同文档,和原有查询逻辑一致 { $match: query }, // 第二步过滤version数组,只保留isDraft为true的元素 { $addFields: { version: { $filter: { input: "$version", as: "ver", cond: { $eq: ["$$ver.isDraft", true] } } } } }, // 分页逻辑和原有保持一致 { $skip: req.body.noOfItems * (req.body.pageNumber - 1) }, { $limit: req.body.noOfItems } ]).exec((err, contracts) => { if (err) return res.json(err); Contract.countDocuments(query).exec((count_error, count) => { if (count_error) return res.json(count_error); return res.json({ total: count, page: req.body.pageNumber, pageSize: contracts.length, contracts: contracts }); }); })
内容的提问来源于stack exchange,提问作者Megha BM
相关产品推荐
相关产品推荐

