【问题标题】:@Query: function ll_to_earth(double precision, double precision) does not exist@Query:函数 ll_to_earth(双精度,双精度)不存在
【发布时间】:2018-04-05 20:11:11
【问题描述】:

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

@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 更改为

@Query(value = "" +
        "SELECT p " +
        "FROM PlaceEntity p " +
        "WHERE FUNCTION('earth_distance', " +
        "   FUNCTION('ll_to_earth', p.latitude, p.longitude), " +
        "   FUNCTION('ll_to_earth', latitude, longitude) " +
        ") < radius")

结果相同。

什么是正确的语法?

【问题讨论】:

    标签: hibernate jpa spring-data-jpa


    【解决方案1】:

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

    启动psql外壳:

    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 展示了如何在必要时提高性能。

    【讨论】:

      【解决方案2】:

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

      对于任何需要相同 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,您需要 spring JPA 不解释的 '@

      无需分页即可获得结果 -

      @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>
      

      【讨论】:

        猜你喜欢
        • 2016-08-17
        • 1970-01-01
        • 2019-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-03
        • 2015-09-13
        • 2018-02-23
        相关资源
        最近更新 更多