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

如何查询自定义类型位置及表中距指定位置最近的地点?

查询自定义类型位置数据及就近地点

一、查询自定义类型的位置数据

不管用Amplify DataStore还是直接调用GraphQL API,都可以直接指定自定义类型内的字段来获取数据:

1. 使用DataStore查询

import { DataStore } from '@aws-amplify/datastore';
import { Post } from './models';

const fetchPostsWithLocation = async () => {
  const posts = await DataStore.query(Post);
  // 取出每个post的位置数据
  posts.forEach(post => {
    console.log(`纬度: ${post.location.lat}, 经度: ${post.location.long}`);
  });
};

2. 使用GraphQL API查询

如果需要精准筛选字段,可直接编写GraphQL查询语句:

query GetPostsWithLocation {
  listPosts {
    items {
      id
      content
      location {
        lat
        long
      }
    }
  }
}

二、查询距离指定位置最近的地点

Amplify默认查询不直接支持地理距离排序,可通过以下两种方案实现:

方案1:自定义GraphQL Resolver(推荐大数据量场景)

  1. 修改Schema添加自定义查询
    在现有schema中新增接收目标经纬度的自定义查询:
a.schema({
  Post: a.model({
    location: a.customType({
      lat: a.float(),
      long: a.float(),
    }),
    content: a.string(),
  }),
  // 新增就近查询接口
  getNearbyPosts: a.query()
    .arguments({
      targetLat: a.float(),
      targetLong: a.float(),
      maxDistance: a.float() // 可选:最大搜索距离(单位:千米)
    })
    .returns(a.ref('Post').list())
    .handler(a.handler.custom({ entry: 'getNearbyPosts.js' })),
});
  1. 编写Resolver逻辑
    在amplify/backend/api/[你的API名称]/resolvers/getNearbyPosts.js中实现距离计算与排序逻辑:
const { DynamoDB } = require('aws-sdk');
const docClient = new DynamoDB.DocumentClient();

// Haversine公式计算两点球面距离(千米)
const haversineDistance = (lat1, lon1, lat2, lon2) => {
  const R = 6371; // 地球平均半径
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLon = (lon2 - lon1) * Math.PI / 180;
  const a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * 
    Math.sin(dLon/2) * Math.sin(dLon/2); 
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  return R * c;
};

exports.handler = async (event) => {
  const { targetLat, targetLong, maxDistance = 10 } = event.arguments;
  
  const params = {
    TableName: process.env.Post_TABLE_NAME,
  };
  
  const result = await docClient.scan(params).promise();
  
  // 过滤范围内地点并按距离排序
  const nearbyPosts = result.Items
    .filter(post => {
      const distance = haversineDistance(targetLat, targetLong, post.location.lat, post.location.long);
      return distance <= maxDistance;
    })
    .sort((a, b) => {
      const distA = haversineDistance(targetLat, targetLong, a.location.lat, a.location.long);
      const distB = haversineDistance(targetLat, targetLong, b.location.lat, b.location.long);
      return distA - distB;
    });
  
  return nearbyPosts;
};
  1. 前端调用自定义查询
import { API } from '@aws-amplify/api';

const fetchNearbyPosts = async (lat, lon, maxDistance) => {
  const result = await API.graphql({
    query: `
      query GetNearbyPosts($targetLat: Float!, $targetLong: Float!, $maxDistance: Float) {
        getNearbyPosts(targetLat: $targetLat, targetLong: $targetLong, maxDistance: $maxDistance) {
          id
          content
          location {
            lat
            long
          }
        }
      }
    `,
    variables: { targetLat: lat, targetLong: lon, maxDistance }
  });
  
  return result.data.getNearbyPosts;
};

方案2:前端本地计算(小数据量场景)

如果数据量不大,可先获取所有数据,再在前端计算距离并排序:

import { DataStore } from '@aws-amplify/datastore';
import { Post } from './models';

const haversineDistance = (lat1, lon1, lat2, lon2) => {
  const R = 6371;
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLon = (lon2 - lon1) * Math.PI / 180;
  const a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * 
    Math.sin(dLon/2) * Math.sin(dLon/2); 
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  return R * c;
};

const fetchNearbyPostsLocally = async (targetLat, targetLong, maxDistance = 10) => {
  const allPosts = await DataStore.query(Post);
  
  return allPosts
    .map(post => ({
      ...post,
      distance: haversineDistance(targetLat, targetLong, post.location.lat, post.location.long)
    }))
    .filter(post => post.distance <= maxDistance)
    .sort((a, b) => a.distance - b.distance);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:35:10