You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Sequelize ORM按经纬度距离查询排序商铺列表

Sequelize 实现周边商铺查询方案

实现核心是通过球面距离公式计算用户与商铺的位置距离,再完成范围筛选、排序,以下是修改后的可运行代码:

const { Op, literal } = require('sequelize');
// 先把传入的经纬度转为数值类型,避免字符串导致计算错误
const userLat = parseFloat(req.query.latitude);
const userLon = parseFloat(req.query.longitude);
const radius = 5; // 自定义查询范围,单位:公里,可根据需求调整
const limit = req.query.limit || 10;
const offset = req.query.offset || 0;
const category_id = req.query.category_id;

const shopLists = await Shop.findAll({
  limit,
  offset,
  attributes: [
    // 按需补充需要返回的商铺字段
    'id', 'name', 'address', 'latitude', 'longitude',
    // 新增计算距离的字段,单位为公里
    [
      literal(`
        6371 * acos(
          cos(radians(${userLat})) 
          * cos(radians(latitude)) 
          * cos(radians(longitude) - radians(${userLon})) 
          + sin(radians(${userLat})) 
          * sin(radians(latitude))
        )
      `),
      'distance'
    ]
  ],
  where: {
    category_id: category_id,
    status: 1,
    // 筛选距离在指定范围内的商铺
    [Op.and]: literal(`
      6371 * acos(
        cos(radians(${userLat})) 
        * cos(radians(latitude)) 
        * cos(radians(longitude) - radians(${userLon})) 
        + sin(radians(${userLat})) 
        * sin(radians(latitude))
      ) <= ${radius}
    `)
  },
  include: {
    model: Category,
    attributes: ['id', 'name']
  },
  // 按距离从近到远排序
  order: [[literal('distance'), 'ASC']]
});

优化说明

如果你使用的是MySQL 5.7及以上版本,可以用内置的ST_Distance_Sphere函数简化计算,写法更简洁、性能更好,直接将上面代码中计算距离的Haversine公式替换为以下内容即可,返回单位同样为公里:

literal(`ST_Distance_Sphere(point(longitude, latitude), point(${userLon}, ${userLat})) / 1000`)

注意事项

  • 如果数据量较大,建议给latitude、longitude、category_id、status字段加联合索引,或者直接使用数据库的空间索引优化查询速度
  • 如果需要自定义返回距离的小数位数,可以在计算距离的SQL外层加ROUND()函数调整精度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 10:00:04