Reputation: 2565
I have a trip model that contains an array of lat/lng pairs
class Trip
include MongoMapper::Document
key :route, Array, # example: [[45,-122], [45.5, -122.5], [45, -123]]
...
end
I would like to perform $near-type queries on the route array, which should be possible according to the documentation .
I would like to find the route nearest to a certain point.
def self.nearest_to(coords)
where(:route => {'$near' => coords}).limit(1).first
end
But this does not work, I get an error that says:
Mongo::OperationFailure: can't find special index: 2d for: { route: { $near: [ 32.80909, -117.1537 ] } }
from /Users/lash/.rvm/gems/[email protected]/gems/mongo-1.3.1/lib/mongo/cursor.rb:101:in `next_document'
from /Users/lash/.rvm/gems/[email protected]/gems/mongo-1.3.1/lib/mongo/cursor.rb:248:in `each'
from /Users/lash/.rvm/gems/[email protected]/gems/mongo-1.3.1/lib/mongo/cursor.rb:267:in `to_a'
from /Users/lash/.rvm/gems/[email protected]/gems/mongo-1.3.1/lib/mongo/cursor.rb:267:in `to_a'
from /Users/lash/.rvm/gems/[email protected]/gems/plucky-0.3.8/lib/plucky/query.rb:76:in `all'
from /Users/lash/code/rails3projects/rideshare/app/models/trip.rb:20:in `nearest'
from (irb):10
from /Users/lash/.rvm/gems/[email protected]/gems/railties-3.0.9/lib/rails/commands/console.rb:44:in `start'
from /Users/lash/.rvm/gems/[email protected]/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in `start'
from /Users/lash/.rvm/gems/[email protected]/gems/railties-3.0.9/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
What is the correct way to query multi-location documents with mongomapper?
Upvotes: 0
Views: 544
Reputation: 2565
The correct answer - as of today - is that you can't. The ruby driver does not yet support mongo 1.3.3, so this type of geo-location query simply isn't possible.
Here is one example of how one might work around the issue in the mean time.
class Trip
include MongoMapper::Document
key :route, Array # example: [[45,-122], [45.5, -122.5], [45, -123]]
...
scope :passes_near, lambda {|coords| where(:id => {'$in' => Trip.near(coords)}) }
def self.near(coords, options = {})
options[:radius] ||= 60
case coords
when Array; coords
when String; coords = Geocoder.coordinates(coords)
end
trips = {}
Trip.all.each do |trip|
dist = trip.route.map{|point| Geocoder::Calculations::distance_between(point, coords)}.min
trips[trip.id] = dist
end
return trips.select {|k, v| v < options[:radius]}.keys
end
end
To find all trips that go near Seattle ([47.6062095, -122.3320708]) I would simply type:
Trip.passes_near("Seattle, WA")
=> #<Plucky::Query _id: {"$in"=>[*lots of ids*}, transformer: #...>
Since a plucky object is returned it would be simple to chain queries together.
Upvotes: 1
Reputation: 3235
You should find some answers on $near at this nice little tutorial: http://mongly.com/
db.treasures.find({location: {$near: [20, -20]}});
Upvotes: 0