Rails Mongoid 的数字型 id 在 Sunspot 报 InvalidObjectId

suupic · 2012年05月02日 · 最后由 sinotao1 回复于 2015年06月16日 · 3380 次阅读

Rails 3.2.3 mongoid 2.4.4 sunspot_mongoid 0.4.1 sunspot_rails 1.3.1 sunspot 1.3.1

在 Content 中用了数字 id,然后发现数字 id 索引出来会报 BSON::InvalidObjectId: illegal ObjectId format 的错误。 部分测试数据使用 BSON 格式的 id,搜索没有发现异常

irb(main):268:0> r = Content.solr_search {  fulltext 'http' }    
=> <Sunspot::Search:{:fq=>["type:Content"], :q=>"http", :fl=>"* score", :qf=>"text_text", :defType=>"dismax", :start=>0, :rows=>30}>
irb(main):269:0> r.results
BSON::InvalidObjectId: illegal ObjectId format: 3433622835126607
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/bson-1.5.2/lib/bson/types/object_id.rb:126:in `from_string'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot_mongoid-0.4.1/lib/sunspot/mongoid.rb:39:in `block in load_all'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot_mongoid-0.4.1/lib/sunspot/mongoid.rb:39:in `map'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot_mongoid-0.4.1/lib/sunspot/mongoid.rb:39:in `load_all'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/abstract_search.rb:228:in `block in populate_hits'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/abstract_search.rb:224:in `each_pair'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/abstract_search.rb:224:in `populate_hits'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/hit.rb:90:in `result'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/abstract_search.rb:275:in `block in verified_hits'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/paginated_collection.rb:50:in `select'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/paginated_collection.rb:50:in `method_missing'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/abstract_search.rb:275:in `verified_hits'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/sunspot-1.3.1/lib/sunspot/search/abstract_search.rb:59:in `results'
        from (irb):2
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/railties-3.2.3/lib/rails/commands/console.rb:47:in `start'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/gems/railties-3.2.3/lib/rails/commands/console.rb:8:in `start'
        from /opt/App/ruby192/lib/ruby/gems/1.9.1/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>'irb(main):003:0> 



而直接请求可以找到记录(ps:之前也报 InvalidObjectId,加了 field :_id, :type => Integer 后正常)

Content.find('3433622835126607')
=> #<Content _id: 3433622835126607>



给 sunspot_mongoid 打了个猴子补丁解决了 把 load 和 load_all 里的 BSON::ObjectId.from_string(id) 修改为

begin
  BSON::ObjectId.from_string(id)
rescue BSON::InvalidObjectId
  id
end

2 楼 已删除
module Mongoid
  module Sunspot
    def self.included(base)
      base.class_eval do
        extend ::Sunspot::Rails::Searchable::ActsAsMethods
        ::Sunspot::Adapters::DataAccessor.register(DataAccessor, base)
        ::Sunspot::Adapters::InstanceAdapter.register(InstanceAdapter, base)
      end
    end

    class InstanceAdapter < ::Sunspot::Adapters::InstanceAdapter
      def id
        @instance.id
      end
    end

    class DataAccessor < ::Sunspot::Adapters::DataAccessor
      def load(id)
        criteria(id).first
      end

      def load_all(ids)
        criteria(ids)
      end

      private

      def criteria(id)
        @clazz.criteria.find(id)
      end
    end
  end
end

用这个替代 sunspot_mongoid

4 楼 已删除
5 楼 已删除

my error : NameError (uninitialized constant Sunspot::Mongoid::DataAccessor::BSON): 使用 3 楼代码 ok but module Sunspot module Mongoid

这几天确实碰到 sunspot with auto_increment_id 的问题,总是提示 2503 is an invalid ObjectId,搞得都有点放弃 mongodb,改用 mysql 了。这下子成功解决,真心高兴。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号