我的latitude
恩赐中有longitude
和Location
。现在我正在使用类似的东西来获得最合适的坐标。
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);
但是现在我想用Query DSL自定义这个查询。我试图找出如何使用OrderSpecifier<?>
也许我应该在我的Location
实体中创建方法,它返回地点和给定坐标之间的距离。但我认为在MODEL层中创建方法并不是解决这个问题的最佳方法。
所以我的主要问题是:如何通过查询DSL中的给定公式(例如Haversine)对记录进行排序
答案 0 :(得分:0)
从我所看到的情况来看,haversine
只是一个具有2个参数纬度和经度的公式(即函数)。确实,在模型中创建方法并不是最好的方法。您应该使用LocationService
类@Service
(如果您使用的是Spring或Springboot),其中包含您所有程序的逻辑。在那里你可以有一个用于计算距离的函数,然后将它传递给你使用QueryDSL
进行排序的函数。
这样的事情:
public class Location {
private int latitude;
private int longitude;
}
@Service
public class LocationServices {
public String haversineCalculation(int locationLat, int locationLong, int latitude, int longitude) {
//Do your calculations here in java
}
public List<Location> findNearest(int latitude, int longitude) {
QLocation location = QLocation.location;
SQLTemplates dialect = new YourSQLDialectTemplate();
SQLQuery query = new SQLQueryImpl(connection, dialect);
List<Location> locations = query
.from(location);
locations.sort((loc1, loc2) -> haversineCalculation(loc1.latitude, loc1.longitude, latitude, longitude).compareTo(haversineCalculation(loc1.latitude, loc1.longitude, latitude, longitude)));
}
}
不幸的是,我不认为OrderSpecifier
可以执行您希望的顺序,因为涉及整个函数,并且订单说明符似乎只能将实体的属性作为排序描述符
答案 1 :(得分:0)
我刚使用Apache Lucene中的Hibernate Search,代码如下所示。
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();