具有可变距离的 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 近/近地查询的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB地理空间查询结果未按距离顺序排列

C# MongoDB 驱动程序 2.0 - 从近处查询返回距离

将此 SQL 查询转换为 mongodb 查询 -

MongoDB pymongo模块 查询

Java实现对mongoDB的两表关联查询

mongodb 根据查询内容导出出错