You need to enable JavaScript to run this app. Mongoose查询GeoJSON餐厅按距离排序时返回结果为undefined的问题
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose查询GeoJSON餐厅按距离排序时返回结果为undefined的问题

核心问题定位
  • 最直接的原因是Promise回调参数顺序使用错误
    Mongoose的Model.find()返回的是标准Promise对象,then()回调只会接收1个参数,即查询成功后的结果集(此处为餐厅列表数组),查询错误会自动进入catch()分支,不会作为参数传入then()。

原代码中then的写法沿用了传统回调的(err, data)格式:

.then(function(err, restaurants){
  console.log(restaurants);
  return res.json({success: true, restaurants: restaurants});
})

实际运行时,Promise会把查询到的餐厅数组赋值给第一个形参err,第二个形参restaurants因为没有对应传参,永远是undefined,最终接口返回的餐厅列表自然为空。

  • 异常处理逻辑存在漏洞
    当前catch中的if(err) throw err会把查询错误抛为未捕获的Promise异常,既不会给前端返回明确的错误信息,极端情况下还可能导致Node进程崩溃,需要直接返回错误响应。
修正后的代码
getRestaurantsNearYou: function(req, res){
  if(req.headers.lng && req.headers.lat){
    const lng = parseFloat(req.headers.lng);
    const lat = parseFloat(req.headers.lat);
    // 校验经纬度格式合法性
    if(isNaN(lng) || isNaN(lat)) {
      return res.json({success: false, msg: res.__('invalidArgumentsErrorMsg')})
    }
    Restaurant.find({
      location: {
        $near: {
          $geometry: {
            type : "Point",
            coordinates : [lng, lat]
          },
          $maxDistance: 5000
        }
      }
    }).then((restaurants) => { // 仅接收查询结果作为参数
      console.log(restaurants);
      return res.json({success: true, restaurants: restaurants});
    }).catch(err => {
      console.error('附近餐厅查询失败:', err);
      return res.json({success: false, msg: res.__('serverErrorMsg')});
    });
  }else{
    return res.json({success: false, msg: res.__('invalidArgumentsErrorMsg')})
  }
}
额外排查建议
  • 确认2dsphere索引已正确构建:可在Mongo shell中执行db.restaurants.getIndexes(),确认存在location字段的2dsphere索引,且索引构建完成(刚新增的索引可能处于后台构建状态,此时查询会返回空但不报错)
  • 确认经纬度顺序正确:GeoJSON格式的coordinates要求为[经度, 纬度],传反会导致查询范围完全偏移到错误位置
  • 可临时调大$maxDistance(比如改为100000即100公里)测试,排除初始5000米的范围设置过小导致无匹配数据的问题

内容的提问来源于stack exchange,提问作者SeriousMonk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 20:36:08