如何在其他函数中使用map方法返回的busId与date字段值
实现方法
你不需要做特殊的参数传递,遍历matchedBus数组时,当前遍历项的busId和date属于当前循环上下文可直接访问的变量,直接在bookings.filter回调中引用即可。以下是可直接落地的完整实现,附带常见踩坑修复:
前置查询优化(减少无效数据拉取)
查询阶段直接通过select指定返回字段,避免拉取无用字段降低性能,同时统一日期格式避免后续匹配出错:
// 先对传入的日期参数做归一化处理,避免时分秒、时区导致匹配失败 const queryDate = new Date(req.query.date); const dayStart = new Date(queryDate.setHours(0, 0, 0, 0)); const dayEnd = new Date(queryDate.setHours(23, 59, 59, 999)); // 查询匹配出发地、目的地、日期的线路 const matchedRoutes = await Route.find({ departureLocation: req.query.from, // 替换为你schema中实际的出发地字段名 arrivalLocation: req.query.to, // 替换为你schema中实际的目的地字段名 date: { $gte: dayStart, $lte: dayEnd } }) .select("_id busId date departureTime arrivalTime") // 只返回业务需要的字段 .populate("busId") // 若需要返回班车详情则保留,否则可删除 .lean(); // 转为普通JS对象,提升后续遍历操作性能 // 提取所有匹配线路ID,一次性查询关联的所有订票记录,避免循环查库产生N+1性能问题 const matchedRouteIds = matchedRoutes.map(route => route._id); const allRelatedBookings = await Booking.find({ routeId: { $in: matchedRouteIds } }) .select("routeId seats") // 只取路线关联ID和已选座位字段 .lean();
核心过滤与座位汇总逻辑
遍历匹配线路时,直接从当前遍历项取busId和date作为过滤条件即可,不需要额外传参:
const busIdWithSeatsObj = {}; for (const route of matchedRoutes) { // 直接从当前线路项取需要的两个字段 const currentBusId = route.busId._id ? route.busId._id.toString() : route.busId.toString(); const currentDate = route.date; const currentRouteId = route._id.toString(); // 过滤当前线路对应的订票记录:因为routeId和线路是一一对应关系,匹配routeId等价于匹配同班车+同日期,性能比单独匹配busId+date更高 const currentRouteBookings = allRelatedBookings.filter(booking => { return booking.routeId.toString() === currentRouteId; }); // 汇总当前线路所有已预订座位 const bookedSeats = currentRouteBookings.reduce((res, booking) => { return res.concat(booking.seats || []); }, []); // 组装结果,用busId+日期作为唯一key,避免同班车跨日期数据覆盖 const resultKey = `${currentBusId}_${currentDate.toISOString().slice(0, 10)}`; busIdWithSeatsObj[resultKey] = { busId: currentBusId, date: currentDate, bookedSeats: [...new Set(bookedSeats)] // 座位去重,避免异常数据导致重复 }; } // 最终随接口返回即可 res.json({ success: true, data: { routeList: matchedRoutes, bookedSeatsMap: busIdWithSeatsObj } });
常见问题修复
如果你之前过滤逻辑不生效,基本是以下三个原因:
- ObjectId类型直接做相等判断:Mongoose返回的ID是特殊ObjectId类型,即使值相同引用不同也会判断为不相等,必须先转成字符串再比较
- 日期匹配精度问题:如果日期字段带有时分秒,直接用
===对比会因为毫秒级差异匹配失败,统一转成时间戳或者按天范围查询即可 - 不要在循环内执行数据库查询:提前一次性拉取所有关联数据到内存中过滤,接口性能会提升数倍到数十倍不等
内容的提问来源于stack exchange,提问作者user19038939
相关产品推荐
相关产品推荐

