MongoDb near / geonear查询可变距离 [英] MongoDb near/geonear query with variable distance

查看:1660
本文介绍了MongoDb near / geonear查询可变距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



集合中的条目示例: $ b $

我想执行查询,其中距离是集合中的动态字段。 b

  {
名称:'myName',
位置:{lat:10,lng:20},
maximumDistance: 10
}
{
名称:'myName2',
位置:{lat:20,lng:20},
maximumDistance:100
}

我的目标是从此集合中检索 location 所有元素接近给定的位置,让我们假设(10,10),但计算的距离小于这个 maximumDistance 字段。



我可以在近查询中将maxDistance设置为一个常量值(足以检索我想要的所有元素),然后在我的java代码中执行过滤器,但我会更喜欢在查询上执行它,这可能太面向SQL了。

解决方案

由于您无法动态设置每个文档的距离,因此您无法使用普通查询执行此操作。从MongoDB 2.4开始,你可以使用聚合框架来完成这一任务,因为他们已经将geoNear运算符添加到流水线开始。



第一阶段将是geoNear,它非常类似于geonear命令。我们还将获得从指定点(10,10)到该文档的距离。



第二阶段我们需要使用项目操作员来广告最大距离字段和计算出的地理距离之间的差别。最后,我们匹配那些具有正的三角洲((最大距离)> 0)的文件。

p>

以下是使用 Asynchronous Java Driver 的帮助类。


$ b

  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( (delta,
subtract(field(maximumDistance),
field(distance))))$(位置,maximumDistance),
set b $ b .match(where(delta)。greaterThanOrEqualTo(0))。build();

System.out
.println(new ArrayElement(pipeline,aggregate.getPipeline()));
}
}

这里是管道被创建:

  pipeline:[
{
'$ geoNear':{
附近:[
10,
10
],
distanceField:'distance',
spherical:false,
uniqueDocs:true
}
},
{
'$ project':{
名称:1,
位置:1,
maximumDistance:1,
delta :{
'$ subtract':[
'$ maximumDistance',
'$ distance'
]
}
}
},
{
'$ match':{
delta:{'$ gte':0}
}
}
]

HTH - Rob。



PS上面的建设者正在使用该驱动程序的1.2.0版本的预发行版本。该代码正在通过构建矩阵输入,并将于2013年3月22日星期五之前发布。


I would like to execute a query where the distance is a dynamic field from the collection.

Example of entries in the collection:

{
  name:'myName',
  location: {lat:10, lng:20},
  maximumDistance: 10
}
{
  name:'myName2',
  location: {lat:20, lng:20},
  maximumDistance: 100
}

My goal is to retrieve all the elements from this collection where this location is close to a given location, let's say (10,10) but where the calculated distance is less than this maximumDistance field.

I can set maxDistance to a constant value (high enough to retrieve all the elements I want) in the near query and then do the filter in my java code but I would prefer to do it on the query it is maybe too SQL oriented.

解决方案

You won't be able to do this with a normal query as you can't dynamically set the distance per document. As of MongoDB 2.4 you can do this with the aggregation framework as they have added the geoNear operator to the starts of pipelines.

The first stage will be the geoNear which is very similar to the geonear command. We will also get the distance from the point specified (10,10) to the document as a result.

The second stage we will need to use the project operator to ad the different between the maximumDistance field and the computed geoNear distance.

Lastly, we match those documents that have a positive delta ((max - distance) > 0).

Here is the pipeline using the Asynchronous Java Driver's helper classes.

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()));
    }
}

And here is the pipeline is created:

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 - Rob.

P.S. The builders above are using a pre-release of the 1.2.0 version of the driver. The code is going through the build matrix as I type and should be released by Friday, March 22, 2013.

这篇关于MongoDb near / geonear查询可变距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆