@Query:函数ll_to_earth(双精度,双精度)不存在

时间:2018-04-05 20:11:12

标签: hibernate jpa spring-data-jpa

我正在尝试实现以下查询,以便在给定位置(lat,lng)的情况下获取特定半径(以米为单位)内的位置:

SUPERUSER_ID

但是,运行它会抛出:

@RepositoryRestResource(collectionResourceRel = "places", path = "places")
public interface PlaceRepository extends JpaRepository<PlaceEntity, Long> {

    @Query(value = "" +
            "SELECT p " +
            "FROM PlaceEntity p " +
            "WHERE earth_distance( " +
            "   ll_to_earth(p.latitude, p.longitude), " +
            "   ll_to_earth(latitude, longitude) " +
            ") < radius")
    List<PlaceEntity> findByLocationAndRadius(@Param("latitude") Float latitude,
                                              @Param("longitude") Float longitude,
                                              @Param("radius") Integer radius);
}

我还尝试更改集Caused by: org.postgresql.util.PSQLException: ERROR: function ll_to_earth(double precision, double precision) does not exist Hint: No function matches the given name and argument types. You might need to add explicit type casts. Position: 343 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2284) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2003) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:200) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:424) at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:161) at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114) at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52) at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60) ... 76 more 以及将nativeQuery = true更改为

@Query

具有相同的结果。

这个的正确语法是什么?

2 个答案:

答案 0 :(得分:1)

https://johanndutoit.net/searching-in-a-radius-using-postgres/我发现我必须安装一些扩展程序:

启动psql shell:

psql postgres -h localhost -d <database-name>

执行:

<database-name>=# CREATE EXTENSION cube;
<database-name>=# CREATE EXTENSION earthdistance;

此外,正确设置nativeQuery = true和参考参数:

@Query(value = "" +
        "SELECT * " +
        "FROM place " +
        "WHERE earth_distance( " +
        "   ll_to_earth(place.latitude, place.longitude), " +
        "   ll_to_earth(:latitude, :longitude) " +
        ") < :radius", nativeQuery = true)
List<PlaceEntity> findByLocationAndRadius(@Param("latitude") Float latitude,
                                          @Param("longitude") Float longitude,
                                          @Param("radius") Integer radius);

注意:这可能会变慢。 link显示了如何在必要时提高效果。

答案 1 :(得分:1)

如果不存在则创建扩展多维数据集 如果地球距离不存在,请创建扩展

对于需要相同JPA版本的任何人

 @Query(
        """
                FROM Place pl
                WHERE 
                FUNCTION('cube_contains',
                 FUNCTION('earth_box',
                  FUNCTION('ll_to_earth', :latitude, :longitude),
                  :radiusInMeters),
                 FUNCTION('ll_to_earth', pl.latitude, pl.longitude) 
                  ) = TRUE
                """)
    fun getPlacesNear(
        pageable: Pageable,
        @Param("latitude") latitude: Double,
        @Param("longitude") longitude: Double,
        @Param("radiusInMeters") radiusInMeters: Int
    ): Page<Place>

这就像传呼和距离支持的魅力

出于某些奇怪的原因

@Query(
        """
                FROM Place pl
                WHERE 
                 FUNCTION('ll_to_earth', pl.latitude, pl.longitude)                    
                 < FUNCTION('earth_box', FUNCTION('ll_to_earth', :latitude, :longitude), :radiusInMeters)
                """)

https://www.postgresql.org/docs/9.5/cube.html#CUBE-GIST-OPERATORS

由于某些奇怪的原因,“ <”无法正常工作,因为在postgres中无法正确解释“ <”,并且给出了错误的结果。

对于postgres,您需要'@ <'符号,该符号不会被Spring JPA解释,因此我不得不切换到使用cube_contains函数

要获得没有分页的结果-

@Query(
            """SELECT *, earth_distance(ll_to_earth(:latitude, :longitude), ll_to_earth(latitude, longitude)) as distance
                    FROM place
                    WHERE  (earth_box(ll_to_earth(:latitude, :longitude), :radiusInMeters) @> ll_to_earth(latitude, longitude))
                    ORDER BY distance ASC
                    """, nativeQuery = true)
        fun getPlacesNear(
            @Param("latitude") latitude: Double,
            @Param("longitude") longitude: Double,
            @Param("radiusInMeters") radiusInMeters: Int
        ): List<Place>?

要获得与本机查询分页的结果,只需提供计数查询-

@Query(
    value = """SELECT *, earth_distance(ll_to_earth(:latitude, :longitude), ll_to_earth(latitude, longitude)) distance 
                    FROM place 
                    WHERE earth_distance(ll_to_earth(:latitude, :longitude), ll_to_earth(latitude, longitude)) < :radiusInMeters                        
                    """,
    countQuery = """
        SELECT COUNT(*) FROM place WHERE (earth_box(ll_to_earth(:latitude, :longitude), :radiusInMeters) @> ll_to_earth(latitude, longitude))
    """, nativeQuery = true)
fun getPlacesNear(
    pageable: Pageable,
    @Param("latitude") latitude: Double,
    @Param("longitude") longitude: Double,
    @Param("radiusInMeters") radiusInMeters: Int
): Page<Place>