mongodb 自定义geoNear
原因
1.使用spring分装的 Aggregation.geoNear 得不到想要的结果数据,总有偏差
1.1 量度(distance) 两点间的距离不正确
1.2 maxDistance 最大距离不生效
spring mongodb 2.1.1
1.pom文件
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
2.spring分装好的 geoNear
NearQuery nearQuery = NearQuery.near(point, Metrics.MILES);
nearQuery.maxDistance(maxDistance);
nearQuery.query(query);
if(sort != null){
nearQuery.with(PageRequest.of(pageNum, pageSize, sort));
} else{
nearQuery.with(PageRequest.of(pageNum, pageSize));
}
List<AggregationOperation> aggregationList = new ArrayList<>();
aggregationList.add(Aggregation.geoNear(nearQuery, distanceField));
if(sort != null){
aggregationList.add(Aggregation.sort(sort));
}
Aggregation agg = Aggregation.newAggregation(aggregationList);
查看源码
1.spring mongodb Operation 都实现了 AggregationOperation类
public interface AggregationOperation {
/**
* Turns the {@link AggregationOperation} into a {@link Document} by using the given
* {@link AggregationOperationContext}.
*
* @return the Document
*/
Document toDocument(AggregationOperationContext context);
}
最终都调用了 toDocument方法
定义 geoNear
public class GeoNearDocument implements AggregationOperation {
private Document nearQuery;
/**
* 自定义 GeoNear
* @param query 查询条件
* @param point 坐标
* @param distanceField 两点之间的距离字段
* @param maxDistance 两点之间的最大距离
*/
public GeoNearDocument(Query query, Point point, String distanceField, double maxDistance) {
Assert.notNull(query, "query must not be null.");
Assert.notNull(point, "point must not be null.");
Assert.notNull(point.getX(), "point x must not be null.");
Assert.notNull(point.getY(), "point y must not be null.");
Assert.notNull(distanceField, "distanceField must not be null.");
this.nearQuery = new Document("near", new Document("type", "Point")
.append("coordinates", new double[]{point.getX(), point.getY()}))
.append("distanceField", distanceField)
.append("query", query.getQueryObject())
.append("num", 1000)
.append("maxDistance", maxDistance)
.append("spherical", true);
}
@Override
public Document toDocument(AggregationOperationContext context) {
Document command = context.getMappedObject(nearQuery);
return new Document("$geoNear", command);
}
}
使用
List<AggregationOperation> aggregationList = new ArrayList<>();
aggregationList.add(new GeoNearDocument(query, point, distanceField, maxDistance));
aggregationList.add(Aggregation.skip((pageNum-1) * pageSize));
aggregationList.add(Aggregation.limit(pageSize));
if(sort != null){
aggregationList.add(Aggregation.sort(sort));
}
Aggregation agg = Aggregation.newAggregation(
aggregationList);
log.info("坐标查询条件:{}", Arrays.asList(aggregationList));
AggregationResults<T> maps = mongoTemplate.aggregate(agg, collectionName, this.getEntityClass());