具有可变距离的 MongoDb 近/近地查询
Posted
技术标签:
【中文标题】具有可变距离的 MongoDb 近/近地查询【英文标题】:MongoDb near/geonear query with variable distance 【发布时间】:2013-03-20 22:31:33 【问题描述】:我想执行一个查询,其中距离是集合中的一个动态字段。
集合中的条目示例:
name:'myName',
location: lat:10, lng:20,
maximumDistance: 10
name:'myName2',
location: lat:20, lng:20,
maximumDistance: 100
我的目标是从该集合中检索此 位置 靠近给定位置的所有元素,例如 (10,10) 但计算出的距离小于此 最大距离 字段。
我可以在 near 查询中将 maxDistance 设置为一个常量值(足够高以检索我想要的所有元素),然后在我的 java 代码中进行过滤,但我更愿意在查询中执行它可能太 SQL导向的。
【问题讨论】:
【参考方案1】:您无法使用普通查询执行此操作,因为您无法动态设置每个文档的距离。从 MongoDB 2.4 开始,您可以使用聚合框架执行此操作,因为它们已将 geoNear 运算符添加到管道的开头。
第一阶段将是 geoNear,它与 geonear 命令非常相似。作为结果,我们还将得到从指定点(10,10)到文档的距离。
第二阶段,我们将需要使用项目运算符来广告 maximumDistance 字段和计算的 geoNear 距离之间的差异。
最后,我们匹配那些具有正 delta ((max - distance) > 0) 的文档。
这是使用Asynchronous Java Driver 的帮助类的管道。
package example;
import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
import static com.allanbank.mongodb.builder.QueryBuilder.where;
import static com.allanbank.mongodb.builder.expression.Expressions.field;
import static com.allanbank.mongodb.builder.expression.Expressions.set;
import static com.allanbank.mongodb.builder.expression.Expressions.subtract;
import com.allanbank.mongodb.bson.element.ArrayElement;
import com.allanbank.mongodb.builder.Aggregate;
import com.allanbank.mongodb.builder.AggregationGeoNear;
import com.allanbank.mongodb.builder.GeoJson;
public class AggregateGeoNear
public static void main(String[] args)
Aggregate aggregate = Aggregate
.builder()
.geoNear(
AggregationGeoNear.builder()
.location(GeoJson.p(10, 10))
.distanceField("distance"))
.project(
include("name", "location", "maximumDistance"),
set("delta",
subtract(field("maximumDistance"),
field("distance"))))
.match(where("delta").greaterThanOrEqualTo(0)).build();
System.out
.println(new ArrayElement("pipeline", aggregate.getPipeline()));
这是创建的管道:
pipeline : [
'$geoNear' :
near : [
10,
10
],
distanceField : 'distance',
spherical : false,
uniqueDocs : true
,
'$project' :
name : 1,
location : 1,
maximumDistance : 1,
delta :
'$subtract' : [
'$maximumDistance',
'$distance'
]
,
'$match' :
delta : '$gte' : 0
]
HTH - 抢劫。
附:上面的构建器使用的是 1.2.0 版本的驱动程序的预发布版本。在我输入代码时,代码正在通过构建矩阵,应该会在 2013 年 3 月 22 日星期五之前发布。
【讨论】:
非常感谢这个非常详细的回答。听起来完全符合我的需要,我现在将尝试弄清楚是否可以对 Spring Data - MongoDb 做同样的事情【参考方案2】:关于如何使用 Spring Data 解决它,我通过构建一个新的 GeoNearOperation 实现来解决它,因为投影中必须包含 maxDistance 字段名称:
public class GeoNearOperation2 implements AggregationOperation
private NearQuery nearQuery;
public GeoNearOperation2(NearQuery nearQuery)
this.nearQuery = nearQuery;
public DBObject toDBObject(AggregationOperationContext context)
DBObject dbObject = context.getMappedObject(nearQuery.toDBObject());
dbObject.put("distanceField", "distance");
return new BasicDBObject("$geoNear",dbObject);
【讨论】:
以上是关于具有可变距离的 MongoDb 近/近地查询的主要内容,如果未能解决你的问题,请参考以下文章