*** NoMethodError异常:未定义的方法`_id'

时间:2017-01-25 14:16:21

标签: mongodb ruby-on-rails-4 elasticsearch tire

我正在研究RubyOnRails应用程序。我通过Tire gem使用Elasticsearch。 Elasticsearch索引了3个模型。这些模型是News,NewsTag和Categorization。新闻与NewsTag有着多对多的关系,而NewsTag与分类有着多对多的关系。所有这些模型都是mongodb。

映射索引: -

    mapping do
        indexes :cover, analyzer: 'snowball'
        indexes :title_en
        indexes :title_ar
        indexes :content_brief_ar
        indexes :content_brief_en
        indexes :body_ar
        indexes :body_en
        indexes :likes, type: 'nested' do
        end
        indexes :comments, type: 'nested' do
        end

        indexes :news_tags, type: 'nested' do
          indexes :name_en, analyzer: 'snowball'
          indexes :name_ar, analyzer: 'snowball'
          indexes :categorizations, type: 'nested' do
            indexes :ar_name, analyzer: 'snowball'
            indexes :en_name, analyzer: 'snowball'
          end
        end
      end
      def to_indexed_json
    {
      cover: self.cover,
      title_ar: self.title_ar,
      title_en: self.title_en,
      content_brief_ar: self.content_brief_ar,
      content_brief_en: self.content_brief_en,
      body_ar: self.body_ar,
      body_en: self.body_en,
      news_tags: self.news_tags,
      likes: self.likes,
      comments: self.comments
    }.to_json
  end

我如何搜索

@news = News.tire.search do
        query do
          nested path: 'news_tags' do
            query do
              boolean do
                  should {terms 'news_tags.categorization_ids', categorization_ids }
              end
            end
          end
        end
        page = page_param.to_i
        search_size = per_page_param.to_i
        from (page - 1) * search_size
        size search_size
      end

这很好用,直到我意识到检索结果的类型不是新闻,它是Item,并且在模型(新闻)中定义了一些经常调用的方法。所以我搜索了将项目包装成新闻,我找到了一些有趣的东西。

将此行添加到config / intializers / tire.rb

Tire.configure do    
   wrapper ProxyObject
end

和此文件app / models / proxy_object.rb

class ProxyObject < SimpleDelegator
  delegate :class, :is_a?, :to => :_proxied_object

  def initialize(attrs={})
    klass = attrs['_type'].camelize.classify.constantize
    @_proxied_object = klass.new
    _assign_attrs(attrs)
    super(_proxied_object)
  end

  private

  def _proxied_object
    @_proxied_object
  end

  def _assign_attrs(attrs={})
     attrs.each_pair do |key, value|
       unless _proxied_object.respond_to?("#{key}=".to_sym)
         _proxied_object.class.send(:attr_accessor, key.to_sym)
       end
       _proxied_object.send("#{key}=".to_sym, value)
     end
  end
end

这个解决方案在Elasticsearch上有一个教程项目非常成功。这个解决方案使我能够调用模型方法。但是,它对我的​​项目不起作用。我注意到一些可能很重要的东西。在新闻索引中。

GET localhost:9200 / news / news / 58889bbb6f6d613fff050000

{
  "_index": "news",
  "_type": "news",
  "_id": "58889bbb6f6d613fff050000",
  "_version": 1,
  "found": true,
  "_source": {
    "cover": "new2",
    "title_ar": "new2",
    "title_en": "new2",
    "content_brief_ar": "new2",
    "content_brief_en": "new2",
    "body_ar": "<p>new2</p>\r\n",
    "body_en": "<p>new2</p>\r\n",
    "news_tags": [
      {
        "_id": "56dec06769702d1578000000",
        "categorization_ids": [
          "5888990f6f6d613fff000000"
        ],
        "created_at": "2016-03-08T14:07:03+02:00",
        "name_ar": "صحة الطفل",
        "name_en": "Baby Health",
        "news_ids": [
          "56dec03569702d156a010000",
          "5704f92769702d4c2b010000",
          "574efc7969702d370a130000",
          "578515d369702d4f11000000",
          "58889bbb6f6d613fff050000",
          "58889c3f6f6d613fff080000"
        ],
        "updated_at": "2016-03-08T14:07:03+02:00"
      }
    ],
    "likes": [],
    "comments": []
  }
}

正如您所注意到的,news_ids嵌入了news_tags,而news_tags中嵌入了news。所以,我觉得有某种递归。

我的问题是,当我在@news对象上应用任何方法时,即使count,从搜索中检索到我收到了错误消息

(byebug) @news.count
  MOPED: 127.0.0.1:27017 COMMAND      database=admin command={:ismaster=>1} runtime: 1.9747ms
  MOPED: 127.0.0.1:27017 UPDATE       database=nabda-net_staging collection=news_tags selector={"$and"=>[{"_id"=>{"$in"=>[]}}]} update={"$pull"=>{"news_ids"=>BSON::ObjectId('5888aaba6f6d6154d0000000')}} flags=[:multi]
                         COMMAND      database=nabda-net_staging command={:getlasterror=>1, :w=>1} runtime: 0.6387ms
*** NoMethodError Exception: undefined method `_id' for #<Hash:0x00000004b78190>

为什么我收到此错误消息? 它甚至不具有描述性。我不知道问题出在哪里。所以,任何人都可以帮助我。

1 个答案:

答案 0 :(得分:1)

我找到了解决方案。在搜索查询中添加load: true将解决问题。

@news = News.tire.search load: true do
        query do
          nested path: 'news_tags' do
            query do
              boolean do
                  should {terms 'news_tags.categorization_ids', categorization_ids }
              end
            end
          end
        end
        page = page_param.to_i
        search_size = per_page_param.to_i
        from (page - 1) * search_size
        size search_size
      end

谢谢大家。