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

Strapi API:如何设置自定义查询服务查找指定范围内的最近机场?

当然可以实现这个需求!我们可以结合geodist工具和Strapi的查询逻辑,轻松筛选出指定距离范围内的机场。下面分两种方案详细说明,你可以根据数据量和性能需求选择:


方案一:使用geodist在内存中筛选(适合小数据量场景)

这种方式先查询所有符合基础条件的机场,再用geodist计算距离并筛选,实现简单,适合机场数据量不大的情况。

1. 确保依赖安装

如果你还没安装geodist,先执行命令:

npm install geodist
# 或者用yarn
yarn add geodist

2. 调整路由配置

原路由的findOne是返回单条数据,我们需要返回多条符合条件的机场,所以修改路由为自定义的findNearby方法:

{
  "method": "GET",
  "path": "/airport/nearby/:latitude/:longitude/:distance?",
  "handler": "Airport.findNearby",
  "config": {
    "policies": []
  }
}

这里的:distance?是可选参数,默认我们可以设为100km。

3. 修改控制器逻辑

替换原有的findOne方法,新增findNearby方法:

const geodist = require('geodist');

module.exports = {
  async findNearby(ctx) {
    // 获取请求参数:当前经纬度、可选的距离阈值(默认100km)
    const { latitude, longitude, distance = 100 } = ctx.params;
    const currentLocation = { 
      lat: parseFloat(latitude), 
      lon: parseFloat(longitude) 
    };

    // 保留你原有的基础筛选和关联字段填充逻辑
    const allAirports = await Airport.find(
      _.pick(ctx.params, _.keys(Airport.schema.paths))
    ).populate(
      _.keys(_.groupBy(_.reject(strapi.models.airport.associations, { autoPopulate: false }), 'alias')).join(' ')
    );

    // 计算每个机场与当前位置的距离,筛选出符合阈值的结果
    const nearbyAirports = allAirports.filter(airport => {
      // 注意:这里假设你的机场模型存储经纬度的字段是`latitude`和`longitude`,如果字段名不同请自行修改
      const airportLocation = { 
        lat: airport.latitude, 
        lon: airport.longitude 
      };
      // 以km为单位计算距离
      const calculatedDistance = geodist(currentLocation, airportLocation, { unit: 'km' });
      return calculatedDistance <= parseFloat(distance);
    });

    return nearbyAirports;
  }
};

方案二:使用数据库地理索引查询(适合大数据量,性能更优)

如果你的机场数据量很大,内存筛选会导致性能瓶颈,这时推荐用数据库的地理查询能力(比如MongoDB的2dsphere索引、PostgreSQL的PostGIS扩展),直接在数据库层面完成筛选,效率更高。

以MongoDB为例:

1. 更新机场模型定义

在models/Airport.settings.json中添加地理字段和索引:

{
  "attributes": {
    // 替换原有的latitude/longitude字段,新增地理点字段
    "location": {
      "type": "geometry",
      "default": "Point",
      "required": true
    },
    // 其他原有字段...
  },
  "indexes": [
    {
      "keys": {
        "location": "2dsphere"
      }
    }
  ]
}

注意:MongoDB存储地理点的格式是[经度, 纬度],和常规的经纬度顺序相反。

2. 修改控制器查询逻辑

async findNearby(ctx) {
  const { latitude, longitude, distance = 100 } = ctx.params;
  // 将km转换为米(MongoDB的$maxDistance默认单位是米)
  const maxDistanceInMeters = parseFloat(distance) * 1000;

  // 直接用MongoDB的地理查询语法筛选附近机场
  const nearbyAirports = await Airport.find({
    location: {
      $nearSphere: {
        $geometry: {
          type: "Point",
          coordinates: [parseFloat(longitude), parseFloat(latitude)] // 注意顺序是[lon, lat]
        },
        $maxDistance: maxDistanceInMeters
      }
    },
    // 保留原有的基础筛选条件
    ..._.pick(ctx.params, _.keys(Airport.schema.paths))
  }).populate(
    _.keys(_.groupBy(_.reject(strapi.models.airport.associations, { autoPopulate: false }), 'alias')).join(' ')
  );

  return nearbyAirports;
}

注意事项

  • 如果你用方案一,要确保机场模型的经纬度字段是数值类型(Number),否则计算距离会出错。
  • 方案二需要数据库支持地理查询,不同数据库的语法略有差异,比如PostgreSQL需要安装PostGIS扩展后使用对应的查询语句。

内容的提问来源于stack exchange,提问作者Bishnu Kumar Bhakat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:53:23