Search code examples
spring-dataquerydsl

Sort by given formula (Haversine) with Query DSL


I have latitude and longitude in my Location enitity. Now im using something like that to get nearest locations by given coords.

String haversine = "(3956 * 2 * ASIN(SQRT(" +
        "POWER(SIN((l.latitude - ?1) *  pi()/180 / 2), 2) +" +
        "COS(l.latitude * pi()/180) * COS(?1 * pi()/180) *" +
        "POWER(SIN((l.longitude - ?2) * pi()/180 / 2), 2) )))";

@Query(value = "SELECT l FROM Location l ORDER BY " + haversine)
List<Location> findNearest(String latitude, String longitude);

But now I want to customize this query with Query DSL. I'm trying to find out how to sort records by given formula and values from entity, using OrderSpecifier<?>

Maybe I should create method in my Location entity which returns me distance between place and given coords. But I think creating method in MODEL layer is not the best approach for this problem.

So my main question is: how to sort records by given formula (eg Haversine) in Query DSL


Solution

  • I just used Apache Lucene from Hibernate Search and code looks like this.

     FullTextEntityManager fullTextSession = Search.getFullTextEntityManager(em);
    
        QueryBuilder builder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Place.class).get();
    
        Double centerLatitude = 51d;
        Double centerLongitude = 17d;
        org.apache.lucene.search.Query luceneQuery = builder
                .spatial()
                .within(1000, Unit.KM)
                .ofLatitude(centerLatitude)
                .andLongitude(centerLongitude)
                .createQuery();
    
        javax.persistence.Query jpaQuery =
                fullTextSession.createFullTextQuery(luceneQuery, Place.class);
    
        em.close();
        return (List<Place>) jpaQuery.getResultList();