2012-10-15 36 views
5

Cách thực hiện giao lộ hoặc truy vấn trùng lặp trong vỏ mongo - những vòng kết nối chồng lên vùng tìm kiếm của tôi? Within chỉ liên quan đến vị trí trung tâm nhưng không bao gồm bán kính của các vòng kết nối khác trong phạm vi tìm kiếm.Làm cách nào để tìm tất cả các vòng kết nối chồng chéo từ bán kính của vòng tròn trung tâm?

Mongo:

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

Bây giờ tôi có thể có được chỉ vòng tròn này trong điểm trung tâm nằm trong khu vực đã tìm kiếm của vòng tròn:

Ruby:

# 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]}}} 

Tôi tạo ra dữ liệu ví dụ với vị trí bổ sung (chỉ số đặc biệt) và bán kính thay vì khoanh tròn vì vòng tròn không được chỉ số địa lý mongodb hỗ trợ:

{ "_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} 

kết quả truy vấn mong muốn:

{ "_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} 

Giải pháp dưới đây giả định rằng tôi nhận được tất cả các hàng và sau đó lọc trên ruby ​​bên bán kính của tôi, nhưng nó chỉ trả về:

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

Tôi nghĩ rằng bạn muốn trở lại "a" , "c" và "d". "e" không trùng lặp với vòng kết nối của bạn. –

+0

Tôi không thể kiểm tra mã của mình lần đầu tiên tôi trả lời. Kiểm tra nó và sửa nó ngay bây giờ. Bạn có thể thấy một mình. Như Asya Kamsky đã nói, bạn chỉ mong đợi một, c và d. Nếu không, thông tin bạn cung cấp cho chúng tôi là sai. – oldergod

+0

Thực ra tôi đã mắc lỗi ở "e". Cả hai giải pháp đều tốt, nhưng bây giờ tôi thấy rằng đối với thời gian hiện tại sẽ sử dụng ruby. Tôi sợ rằng trên kích thước lớn hơn của hồ sơ chương trình của tôi có thể không hoạt động quá nhanh, vì vậy tôi cũng hỏi về cách tiếp cận trong mongo. Cảm ơn bạn! – roza

Trả lời

5

Tôi không quen thuộc với mongodb nhưng tôi giả định rằng trong các giá trị [[x, y], r] có nghĩa là

x: giá trị của tâm trên trục x. y: giá trị của tâm trên trục y. r: bán kính hình tròn.

Giả sử bạn có vòng tròn S mà là tìm kiếm của bạn và một vòng tròn A. ngẫu nhiên Sau đó, bạn có thể calcule khoảng cách giữa trung tâm cả vòng kết nối (S.center và A.center) và xem nếu nó là kém hơn so với những người cả bán kính vòng tròn được thêm (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

Rất tiếc, hiện tại không có khả năng mong muốn truy vấn trực tiếp về các đối tượng trùng lặp, chỉ các điểm trong đối tượng.

Câu trả lời của @ oldergod mô tả thuật toán để tính xem liệu hai vòng kết nối có trùng lặp hay không.

Đây là một công việc xung quanh trong vỏ dựa trên tính toán rằng:

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

On dữ liệu mẫu của bạn đưa vào bộ sưu tập 'vòng tròn':

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

Xin lưu ý rằng kể từ 2.4 (tháng 3 năm 2013) Toán tử geoIntersects $ có sẵn để cung cấp chức năng này cho các chỉ mục GeoJSON và 2dSphere. –

Các vấn đề liên quan