在Spring中使用Haversine公式获取最近的位置

3

我有一个实体在数据库中有两列,就像这样:

@Column(name = "latitude", nullable = false)
private float currentPositionLatitude;

@Column(name = "longitude", nullable = false)
private float currentPositionLongitude;

我在我的数据库(PostgresQl)中有一个实体,它有多个条目,每个条目具有不同的纬度和经度。现在我想给出一个点(lat,lon)和一个半径,并显示所有靠近该点的实体。

我首先尝试使用Harversine公式在Spring Jpa中实现:

   String HAVERSINE_PART = "(6371 * acos(cos(radians(:latitude)) * cos(radians(s.latitude)) *" +
        " cos(radians(s.longitude) - radians(:longitude)) + sin(radians(:latitude)) * sin(radians(s.latitude))))";

    @Query("SELECT currentPositionLatitude,currentPositionLongitude FROM Entity WHERE  '%:HAVERSINE_PART%' < :distance ORDER BY '%:HAVERSINE_PART%' DESC")
      public List<Entity> findEntiryWithLocation(
      @Param("currentPositionLatitude") final float latitude,
      @Param("currentPositionLongitude") final float longitude, @Param("distance") final double distance )

这个方法没有起作用,所以我尝试了:

    @Query("SELECT s FROM Entity s WHERE " + HAVERSINE_PART + " < :distance ORDER BY "+ HAVERSINE_PART + " DESC")
List<Entity> findEntityWithInDistance(
@Param("latitude") double latitude,
 @Param("longitude") double longitude,
 @Param("distance") double distanceWithInKM );

这个也没用,所以我尝试了:

@Query(value = "SELECT *, earth_distance(ll_to_earth(:latitude, :longitude), ll_to_earth(latitude, longitude)) as distance FROM Car WHERE  (earth_box(ll_to_earth(:latitude, :longitude), :radiusInMeters) @> ll_to_earth(latitude, longitude))ORDER BY distance ASC",
nativeQuery = true)
List<Entity> getPlacesNear ( @Param("latitude") float latitude,
                             @Param("longitude")float longitude,
                             @Param("radiusInMeters") float radiusInMeters);

这段代码已经编译通过,但是在我尝试在控制器中传入值时,出现了错误:jdbc error :2022 no dialect mapping。

下面是我的服务方法和控制器代码(数据类型可能已更改):

public List<Entity>showNearestEntityByDistances(float latitude, float longitude, float distance){
        return EntityRepository.getPlacesNear(latitude,longitude,distance);
    }

以及端点:

@GetMapping("/location")
public List<Entity>showEntityNearby(@RequestParam float latitude,@RequestParam float longitude,@RequestParam float distance){
  

    return carService.showNearestEntitysByDistances(latitude,longitude,distance);
}

我已经查看了以下链接: https://www.postgresql.org/docs/current/earthdistance.htmlpostgresql jpa earth_distance query

但是它没有起作用。有人知道我做错了什么吗? 谢谢。

2个回答

1
以下方法适用于我:
首先,运行:
 create extension cube;

 create extension earthdistance; 

这将安装扩展,使得可以进行基于位置的查询而不必安装PostGIS等插件。
然后,不要将你的纬度和经度存储在分开的列中,而是将它们一起存储在“点”类型的列中,记住经度排在纬度之前,例如:
  create table Entity (city varchar(100), location point);

存储您的数据,例如:

insert into places(name, location) values ('lambertville', point((74.9429,40.3659)));
    
insert into places(name, location) values ('ny', point(74.0060, 40.7128));
    
insert into places(name, location) values ('phila', point( 75.1652, 39.9526));

(请注意,Lambertville,NJ大约位于费城和纽约之间的中点。)
然后,例如,如果您想选择与另一个实体距离小于某个特定距离的实体,可以执行以下操作:
select * from places 
 where 
location <@> (select location from places where name = 'ny') < 70  
  and name != 'ny';

或者,如果您已经拥有坐标,并且想要查找一定距离内的实体。
select * from places 
 where 
location <@> point(74.0060, 40.7128) < 70    
  and name != 'ny';

我没有检查过这些查询是否可以适应于JPA的@Query注释,可能会有所不同。


很遗憾,它与@Query注释不兼容。 - Okabe
但是我创建了另一个查询,就像这样: - Okabe
@Query("FROM Entity m where function('cube_contains', function('earth_box', function('ll_to_earth',:#{#latitude},:#{#longitude},:#{#distance}), function ('ll_to_earth',m.latitude,m.longitude)))=TRUE ") List<Entity> getPlacesNear(@Param("latitude") double latitude, @Param("longitude") double longitude, @Param("distance") double distance); - Okabe
它编译通过了,但当我搜索实体时,它不会显示任何内容。 - Okabe

1

我把一些东西改了一下,现在可以运行了:

 @Query(value = "SELECT * FROM Entity s WHERE " + HAVERSINE_PART + " < :distance ORDER BY "+ HAVERSINE_PART + " DESC",nativeQuery = true)
List<Entity> findEntityWithInDistance(
@Param("latitude") double latitude,
 @Param("longitude") double longitude,
 @Param("distance") double distanceWithInKM );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接