MongoDB has a very nice Geospatial Indexing feature. How can I use it in Rails with Mongoid?
MongoDB supports spherical surface calculations on legacy coordinate pairs via a 2dsphere index by converting the data to the GeoJSON Point type. To specify data as legacy coordinate pairs, you can use either an array (preferred) or an embedded document.
Single fieldEach collection in MongoDB automatically has an index on the _id field. This index can then be used to fetch documents from the database efficiently. However, you will need to query data on other specific fields most of the time.
MongoDB can use the intersection of multiple indexes to fulfill queries. In general, each index intersection involves two indexes; however, MongoDB can employ multiple/nested index intersections to resolve a query.
A clustering index is an index that stores the entire document, not just the defined key. A common example is InnoDB's primary key in MySQL. InnoDB stores the entire row in the primary key, therefore making it clustering. MongoDB has no clustering indexes, as the entire document is stored in a data heap.
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'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 }
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With