2012-10-15 56 views
5

如何在mongo shell中进行交叉或重叠查询 - 哪些圈子与我的搜索区域重叠? Within仅涉及中心位置,但不包括搜索范围内其他圆的半径。如何找到中心圆半径的所有重叠圆?

蒙戈:

# My bad conception: 
var search = [[30, 30], 10] 
db.places.find({circle : {"$within" : {"$center" : [search]}}}) 

现在我仅能够获得中心点在这个圈子在于圈的搜索区域:

红宝石:

# field :circle, type: Circle # eg. [ [ 30, 30 ], 10 ] 
field :radius, type: Integer 
field :location, :type => Array, :spatial => true 
spatial_index :location 

Places.within_circle(location: [ [ 30, 30 ], 10 ]) 

# {"$query"=>{"location"=>{"$within"=>{"$center"=>[[30, 30], 10]}}} 

我创建示例数据与额外的位置(特殊索引)和半径代替圈,因为圆不被mongodb地理索引支持:

{ "_id" : 1, "name" : "a", "circle" : [ [ 5, 5 ], 40 ], "latlng" : [ 5, 5 ], "radius" : 40 } 
{ "_id" : 2, "name" : "b", "circle" : [ [ 10, 10 ], 5 ], "latlng" : [ 10, 10 ], "radius" : 5 } 
{ "_id" : 3, "name" : "c", "circle" : [ [ 20, 20 ], 5 ], "latlng" : [ 20, 20 ], "radius" : 5 } 
{ "_id" : 4, "name" : "d", "circle" : [ [ 30, 30 ], 50 ], "latlng" : [ 30, 30 ], "radius" : 50} 
{ "_id" : 5, "name" : "e", "circle" : [ [ 80, 80 ], 30 ], "latlng" : [ 80, 80 ], "radius" : 30} 
{ "_id" : 6, "name" : "f", "circle" : [ [ 80, 80 ], 20 ], "latlng" : [ 80, 80 ], "radius" : 20} 

所需的查询结果:下面

{ "_id" : 1, "name" : "a", "circle" : [ [ 5, 5 ], 40 ], "latlng" : [ 5, 5 ], "radius" : 40 } 
{ "_id" : 3, "name" : "c", "circle" : [ [ 20, 20 ], 5 ], "latlng" : [ 20, 20 ], "radius" : 5 } 
{ "_id" : 4, "name" : "d", "circle" : [ [ 30, 30 ], 50 ], "latlng" : [ 30, 30 ], "radius" : 50} 
{ "_id" : 5, "name" : "e", "circle" : [ [ 80, 80 ], 30 ], "latlng" : [ 80, 80 ], "radius" : 30} 

解决方案假定我得到的所有行,然后在Ruby方面我半径的滤镜,但它只返回:

{ "_id" : 4, "name" : "d", "circle" : [ [ 30, 30 ], 50 ], "latlng" : [ 30, 30 ], "radius" : 50} 
+0

我想你想回去“一” ,“c”和“d”。 “e”与您的圈子不重叠。 –

+0

我第一次回答时无法检查我的代码。检查它并立即修复它。你可以自己看。 Asya Kamsky说,你期望只有a,c和d。否则,你给我们的信息是错误的。 – oldergod

+0

其实我在“e”上犯了一个错误。两种解决方案都很好,但现在我发现目前的时间会使用ruby。我担心,如果记录规模较大,我的程序运行速度可能不太快,所以我也询问了mongo中的方法。谢谢! – roza

回答

5

我不熟悉与mongodb,但我假设在[[x,y],r]值意味着

x:中心轴x上的值。 y:轴y上中心的值。 r:圆半径。

假设你有一个圆S是你的搜索和随机循环A.然后,你可以calcule两个圆中心之间的距离(S.center和A.center),看看它是否是及不上两圆弧半径增加(Sr + Ar)。

def distance_between(a, b) 
    ((b.first - a.first)**2 + (b.last - a.last)**2)**0.5 
end 

elements = [{ _id: 1, name: "a", circle: [ [ 5, 5 ], 40 ] }, 
      { _id: 2, name: "b", circle: [ [ 10, 10 ], 5 ] }, 
      { _id: 3, name: "c", circle: [ [ 20, 20 ], 5 ] }, 
      { _id: 4, name: "d", circle: [ [ 30, 30 ], 50 ] }, 
      { _id: 5, name: "e", circle: [ [ 80, 80 ], 30 ] }, 
      { _id: 6, name: "f", circle: [ [ 80, 80 ], 20 ] }] 
search = [[30, 30], 10] 

elements.select do |elem| circle = elem[:circle] 
    distance_between(circle.first, search.first) <= circle.last + search.last 
end 

#{:_id=>1, :name=>"a", :circle=>[[5, 5], 40]} 
#{:_id=>3, :name=>"c", :circle=>[[20, 20], 5]} 
#{:_id=>4, :name=>"d", :circle=>[[30, 30], 50]} 
3

不幸的是,目前mongo没有能力直接查询重叠对象,只有对象内的点。

@ oldgod的答案描述了计算两个圆是否重叠的算法。

这是基于这样计算的壳变通办法:

function distance(a, b) { 
    return Math.pow(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2), 0.5); 
} 

在您的样本数据插入到收集“圆圈”:

> db.circle.find().forEach(
    function(c) { 
     if ((distance(c.latlng, search.latlng) < c.radius + search.radius)) 
      { 
       print(c.name); 
      } 
    }) 
a 
c 
d 
> 
+0

请注意,截至2。4(2013年3月)$ geoIntersects操作符可用于为GeoJSON和2dSphere索引提供此功能。 –