Невозможно выполнить геозапрос во встроенном документе с помощью Mongoid и Geocoder

(Ruby 1.9.3, MongoDB 2.0.4, Rails 3.2, Mongoid 2.4, Geocoder 1.1.1)

У меня есть следующие модели:

class Company
  include Mongoid::Document

  embeds_one :office

  index [[ "office.coordinates", Mongo::GEO2D ]]
end

class Office
  include Mongoid::Document
  include Geocoder::Model::Mongoid

  geocoded_by :address

  field :city,        :type => String
  field :state,       :type => String
  field :coordinates, :type => Array

  embedded_in :company

  after_validation :geocode

  def address
    "#{city}, #{state}"
  end
end

Я делаю это в консоли:

> c = Company.new
 => #<Company _id: 4f885aa56d20f03898000003, _type: nil> 
> c.office = Office.new(:city => "San Francisco", :state => "CA")
 => #<Office _id: 4f885ab66d20f03898000004, _type: nil, city: "San Francisco", state: "CA", coordinates: nil> 
> c.save
 => true

Все идет нормально. Но затем я пытаюсь получить компанию, выполнив геозапрос к ее встроенному документу (офису):

> Company.where(:office.near => Company.first.office.to_coordinates).first
Mongo::OperationFailure: can't find special index: 2d for: { office: { $near: [ -122.4194155, 37.7749295 ] } }
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/mongo-1.6.2/lib/mongo/cursor.rb:144:in `next'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/mongo-1.6.2/lib/mongo/collection.rb:288:in `find_one'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/mongoid-2.4.8/lib/mongoid/collections/master.rb:25:in `block in find_one'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/mongoid-2.4.8/lib/mongoid/collections/retry.rb:29:in `retry_on_connection_failure'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/mongoid-2.4.8/lib/mongoid/collections/master.rb:24:in `find_one'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/mongoid-2.4.8/lib/mongoid/collection.rb:60:in `find_one'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/mongoid-2.4.8/lib/mongoid/contexts/mongo.rb:203:in `first'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/mongoid-2.4.8/lib/mongoid/criteria.rb:45:in `first'
    from (irb):2
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.3/lib/rails/commands/console.rb:47:in `start'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.3/lib/rails/commands/console.rb:8:in `start'
    from /Users/raphael/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.3/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

Что я делаю неправильно? Я пробежал rake db:mongoid:create_indexes.


person Raphael    schedule 13.04.2012    source источник


Ответы (1)


Вам нужно запустить запрос для встроенного поля:

Company.where(:'office.coordinates'.near => Company.first.office.to_coordinates).first

Если вы хотите использовать область near, созданную гемовским камнем геокодера в Office, вы можете сделать что-то вроде следующего:

# in Company.rb
self.near(office, radius = 20, conditions = {})
  self.where(conditions).tap do |criteria|
    near_criteria = Office.scopes[:near].conditions.call(office, radius)

    criteria.selector[:'office.coordinates'] = near_criteria.selector[:coordinates]
  end
end

Это создает Company#near, который принимает объект Office. Он вставит запрос, созданный областью действия Office#near, в запрос для компании.

person mikeycgto    schedule 13.04.2012
comment
Хотел обновить геокодер, чтобы быть в курсе встроенных моделей для монгоидов. Хотя легче сказать, чем сделать :D - person mikeycgto; 13.04.2012