如何在Express+MongoDB中结合TomTom API筛选距离达标餐厅
筛选距离用户位置小于指定距离的餐厅
问题背景
我拥有一个餐厅集合,每个餐厅包含lat(纬度)和lon(经度)字段,前端会传入用户的位置信息,我使用TomTom Route API来计算距离。现有以下两个函数:
原计算距离函数
export const getDistance = async(res, mylat, mylong, lat, long) => { try { const distance = await axios.get(`https://api.tomtom.com/routing/1/calculateRoute/${mylat},${mylong}:${lat},${long}/json?key=${APIKEY}`) return res.status(200).json(position.data.routes[0].summary.lengthInMeters) } catch (error) { res.status(400).json({message: error.message}) } }
原获取餐厅函数
export const getRestaurants = async (req, res) => { try { const restaurants = await RestaurantModel.find() res.status(200).json(restaurants) } catch (error) { res.status(400).json({message: error.message}) } }
需求:如何使用getDistance()函数返回距离小于X米的餐厅?
解决方案
1. 重构getDistance函数
原函数直接向客户端返回响应,无法在其他逻辑中复用。我们需要修改它,让它返回计算出的距离数值(而非直接处理响应),同时修正原代码中变量名错误:
export const getDistance = async(mylat, mylong, lat, long) => { try { const response = await axios.get(`https://api.tomtom.com/routing/1/calculateRoute/${mylat},${mylong}:${lat},${long}/json?key=${APIKEY}`) // 修正原代码中position变量的错误,改为response return response.data.routes[0].summary.lengthInMeters } catch (error) { throw new Error(`计算距离失败: ${error.message}`) } }
2. 修改餐厅查询函数,实现筛选逻辑
新建或修改原函数,让它接收用户位置和最大距离参数,筛选出符合条件的餐厅:
export const getRestaurantsWithinDistance = async (req, res) => { try { // 从请求参数中获取用户位置和最大距离 const { mylat, mylong, maxDistance } = req.query if (!mylat || !mylong || !maxDistance) { return res.status(400).json({ message: '缺少必要参数:mylat、mylong、maxDistance' }) } // 转换为数值类型 const userLat = parseFloat(mylat) const userLon = parseFloat(mylong) const maxDist = parseFloat(maxDistance) // 获取所有餐厅数据 const allRestaurants = await RestaurantModel.find() // 并行计算所有餐厅的距离,提高效率 const filteredResults = await Promise.all( allRestaurants.map(async (restaurant) => { try { const distance = await getDistance(userLat, userLon, restaurant.lat, restaurant.lon) // 筛选距离小于等于指定值的餐厅,同时带上距离信息 if (distance <= maxDist) { return { ...restaurant.toObject(), distance } } return null } catch (err) { console.error(`计算餐厅${restaurant._id}距离失败:`, err) return null } }) ) // 过滤掉计算失败或不符合条件的餐厅 const validRestaurants = filteredResults.filter(Boolean) res.status(200).json(validRestaurants) } catch (error) { res.status(400).json({ message: error.message }) } }
关键说明
- 并行计算:使用
Promise.all并行处理所有餐厅的距离计算,比串行循环更高效 - 参数校验:提前检查必要参数,避免后续逻辑出错
- 容错处理:单个餐厅距离计算失败时,仅记录错误并跳过该餐厅,不影响整体结果
- 增强返回数据:给符合条件的餐厅附加
distance字段,方便前端直接使用
内容的提问来源于stack exchange,提问作者HICHEM NEGGAZ
相关产品推荐
相关产品推荐

