如何使用mongomapper对lat / lng对数组执行$ near-like查询

时间:2011-08-19 03:32:34

标签: mongodb mongomapper

我有一个包含lat / lng对数组的旅行模型

class Trip
  include MongoMapper::Document

  key :route, Array, # example: [[45,-122], [45.5, -122.5], [45, -123]]
  ...
end

我想在路由数组上执行$ near-type查询,这应该可以根据documentation进行。

我想找到最接近某一点的路线。

def self.nearest_to(coords)
  where(:route => {'$near' => coords}).limit(1).first
end

但是这不起作用,我得到一个错误,上面写着:

Mongo::OperationFailure: can't find special index: 2d for: { route: { $near: [ 32.80909, -117.1537 ] } }
    from /Users/lash/.rvm/gems/ruby-1.9.2-p290@rails3.0.9/gems/mongo-1.3.1/lib/mongo/cursor.rb:101:in `next_document'
    from /Users/lash/.rvm/gems/ruby-1.9.2-p290@rails3.0.9/gems/mongo-1.3.1/lib/mongo/cursor.rb:248:in `each'
    from /Users/lash/.rvm/gems/ruby-1.9.2-p290@rails3.0.9/gems/mongo-1.3.1/lib/mongo/cursor.rb:267:in `to_a'
    from /Users/lash/.rvm/gems/ruby-1.9.2-p290@rails3.0.9/gems/mongo-1.3.1/lib/mongo/cursor.rb:267:in `to_a'
    from /Users/lash/.rvm/gems/ruby-1.9.2-p290@rails3.0.9/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/ruby-1.9.2-p290@rails3.0.9/gems/railties-3.0.9/lib/rails/commands/console.rb:44:in `start'
    from /Users/lash/.rvm/gems/ruby-1.9.2-p290@rails3.0.9/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in `start'
    from /Users/lash/.rvm/gems/ruby-1.9.2-p290@rails3.0.9/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>'

使用mongomapper查询多位置文档的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

正确答案 - 截至今天 - 是你做不到的。 ruby驱动程序尚不支持mongo 1.3.3,因此这种类型的地理位置查询根本不可能。

以下是一个人如何解决这个问题的例子。

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 

要找到西雅图附近的所有旅行([47.6062095,-122.3320708]),我只需输入:

Trip.passes_near("Seattle, WA") 
=> #<Plucky::Query _id: {"$in"=>[*lots of ids*}, transformer: #...> 

由于返回了一个丰富的对象,因此将查询链接起来很简单。

答案 1 :(得分:0)

你应该在这个漂亮的小教程上找到$ near附近的答案:http://mongly.com/

db.treasures.find({location: {$near: [20, -20]}});