15

MongoDB has a very nice Geospatial Indexing feature. How can I use it in Rails with Mongoid?

CamelCamelCamel
  • 5,200
  • 8
  • 61
  • 93

3 Answers3

50

You can define geo indexes like this in mongoid

class Item
  include Mongoid::Document

  field :loc, :type => Array

  index(
      [
          [:loc, Mongo::GEO2D]             
      ], background: true

  )
end

And for queries

$near command (without maxDistance)

 location = [80.24958300000003, 13.060422]
 items = Item.where(:loc => {"$near" => location})

$near command (with maxDistance)

 distance = 10 #km
 location = [80.24958300000003, 13.060422]
 items = Item.where(:loc => {"$near" => location , '$maxDistance' => distance.fdiv(111.12)})

Convert distance by 111.12 (one degree is approximately 111.12 kilometers) when using km, or leave distance as it is on using degree

$centerSphere / $nearSphere queries

location = [80.24958300000003, 13.060422]
items = Item.where(:loc => {"$within" => {"$centerSphere" => [location, (distance.fdiv(6371) )]}})

This will find the items within the 10 km radius. Here we need to convert the distance/6371(earth radius) to get it work with km.

$box (bounding box queries)

 first_loc = [80.24958300000003, 13.060422]
 second_loc = [81.24958300000003, 12.060422]
 items = Item.where(:loc => {"$within" => {"$box" => [first_loc, second_loc]}})

This will help you to find the items within the given bounding box.

RameshVel
  • 64,778
  • 30
  • 169
  • 213
  • When I try using $near command (with maxDistance) it returns an error: geo values have to be numbers: { $maxDistance: 0.001799856011519079, $near: [ 80.249, 13.060422 ] } Any thoughts? It works with just "$near" in place, but when I add "$maxDistance", it chokes. – Vasily Jan 09 '12 at 03:27
  • @Vasily, i am not sure.. the $near query with $maxdistance works perfectly fine with the values you specified. `Item.where(:loc => {"$near" => [ 80.249, 13.060422 ] , '$maxDistance' => 0.001799856011519079})`. it works fine.. May be you can show me the query you were trying? we ll see then – RameshVel Jan 09 '12 at 08:02
  • I've got same error when I use maxDistance. Ruby 1.8. Did you guys find a solution? – Mike Bevz Feb 23 '12 at 10:09
7

RameshVel's answer is great.

As an update, in Mongoid 3.0.4, I had to define the index as follows to make it work with rake db:mongoid:create_indexes:

index(
  { loc: Mongo::GEO2D },
  { background: true }
)
Jake Vose
  • 91
  • 1
  • 2
  • 7
    Actually this didn't work for me with `Mongoid 3.0.0`, the documentation indicates the following format `index({ loc: "2d" }, { min: -200, max: 200 })`. Cheers. – rjgonzo Nov 23 '12 at 21:20
1

All those answers are a outdated with newest versions of MongoDB and will throw some uninitialized constant Mongo::GEO2D

For mongoid 4/5, I suggest you have look at the mongoid-geospatial gem if you need to play with 2D Objects or coordinates.

Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164