【问题标题】:Java springboot Specification proximity complex trigonometry queryjava springboot规范近似复三角查询
【发布时间】:2021-02-11 03:39:28
【问题描述】:

我正在创建一个应用程序,用户可以在其中通过多种(可选)过滤器过滤结果,其中之一是按邻近度搜索。我正在使用 org.springframework.data.jpa.domain.Specification 动态构建查询,根据提供的参数,其中大部分是简单的 ge/le 一些整数值。 我的 where 子句:(location_lng/lat 是数据库中的值,其中数字是与查询一起提供的坐标,

SELECT *
FROM rental 
WHERE(
    6371 * acos(
      cos( radians(52.2477331) ) * cos( radians( location_lat ) )
      *
      cos( radians( location_lng ) - radians(21.0136079) )
      +
      sin( radians(52.2477331) )
      *
      sin( radians( location_lat ) )
    )
  ) < 10

我的后端即时使用这种方法查询存储库:

public Page<RentalDTO> getByCriteria(RentalSearchCriteria cr,
                                         Optional<Integer> page,
                                         Optional<String> sort,
                                         Optional<Integer> size,
                                         Optional<Sort.Direction> order) {
        return rentalRepository.findAll(
                where(
                        priceFrom(cr.getPriceFrom())
                                .and(inProximity(cr.getDist(),cr.getLat(),cr.getLng()))
                                .and(priceTo(cr.getPriceTo()))
                                .and(sizeFrom(cr.getSizeFrom()))
                                .and(sizeTo(cr.getSizeTo()))
                                .and(buildFrom(cr.getBuildFrom()))
                                .and(builtTo(cr.getBuildTo()))
                                .and(roomFrom(cr.getRoomFrom()))
                                .and(roomTo(cr.getRoomTo()))
                                .and(moveInAt(cr.getMoveInTo()))
                                .and(tagsIncluded(cr.getFeatures()))
                ),
                PageRequest.of(
                        page.orElse(0),
                        size.orElse(3),
                        order.orElse(Sort.Direction.ASC),
                        sort.orElse("price"))
        ).map(RentalDTO::createFrom);
    }

和规范(这个暂时是空的):

    public static Specification<Rental> inProximity(Integer distance, Double lat, Double lng) {
        if (distance == null || lat == null || lng == null) {
            return null;
        } else {
            return (root, query, cb) -> {
                return null; // todo 
            };
        }
    }

查询使用 group by,而其他查询不使用,但肯定有一些方法可以不用它,因为我不需要检查整个表来计算特定行的距离,也许是一些子查询或这样,不太确定如何处理这个过滤器。

【问题讨论】:

    标签: java sql spring-boot jpa spring-data-jpa


    【解决方案1】:

    我最终创建了一个 postgreSQL 函数,并在规范中使用了该函数:

    create or replace function distance(lat double precision, lng double precision, db_lat double precision, db_lng double precision)
      returns double precision as $dist$ 
      begin 
      return 
      6371 * acos(
          cos(radians(lat)) * cos(radians(db_lat))
          *
          cos(radians(db_lng) - radians(lng))
          +
          sin(radians(lat))
          *
          sin(radians(db_lat))
        );
        
        
        end;
        $dist$ language plpgsql;
    

    Springboot:

        public static Specification<Rental> inProximity(Double distance, Double lat, Double lng) {
            if (distance == null || lat == null || lng == null) {
                return null;
            } else {
                return (root, query, cb) ->
                        cb.lessThanOrEqualTo(
                                cb.function("distance", Double.class,
                                        cb.literal(lat), cb.literal(lng), root.get("locationLat"), root.get("locationLng")),
                                distance
                        );
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 2021-03-04
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      • 2013-02-15
      • 2011-12-22
      • 1970-01-01
      相关资源
      最近更新 更多