Node.js中执行动态MongoDB查询的最优方法:空数组过滤条件处理
问题根源
当userHospitalQuery为空数组时,MongoDB的$in: []语法不会匹配任何文档,导致查询结果不符合预期,你需要在数组为空时自动忽略该过滤条件。
方案1:对象展开运算符(最推荐,符合你不能在对象内写if的要求)
利用JS短路求值+对象展开特性,仅当数组非空时才将医院过滤条件加入查询对象:
const userHospitalQuery = [req.query.hospital || []].flat(); const filter = { ...(userHospitalQuery.length && { "staff.hospital": { $in: userHospitalQuery } }), organisation: { $eq: "Test" }, isDeleted: { $eq: false }, }; const staff = await User.find(filter).sort({ dateAdded: -1 });
逻辑说明:当userHospitalQuery.length为0时,&&运算返回假值,展开假值到对象中不会新增任何属性,自动跳过该过滤条件。
方案2:先定义基础条件,外部追加可选条件
如果不习惯展开语法,可以先写固定生效的过滤规则,再判断是否追加医院条件:
const userHospitalQuery = [req.query.hospital || []].flat(); // 固定生效的过滤条件 const filter = { organisation: { $eq: "Test" }, isDeleted: { $eq: false }, }; // 数组非空时追加医院过滤条件 if (userHospitalQuery.length) { filter["staff.hospital"] = { $in: userHospitalQuery }; } const staff = await User.find(filter).sort({ dateAdded: -1 });
方案3:MongoDB原生逻辑处理(无需调整JS对象结构)
如果你必须把所有条件都写在filter对象内部,可以用MongoDB的$expr运算符实现条件判断,空数组时该过滤规则自动永远为真:
const filter = { $expr: { $and: [ { $or: [ { $eq: [userHospitalQuery.length, 0] }, { $in: ["$staff.hospital", userHospitalQuery] } ] }, { $eq: ["$organisation", "Test"] }, { $eq: ["$isDeleted", false] } ] } };
注意该方案需要MongoDB在查询时执行运算,性能略低于前两种,优先选择前两种方案即可。
内容的提问来源于stack exchange,提问作者Emil C.
相关产品推荐
相关产品推荐

