繁体   English   中英

Rails Elasticsearch-多个过滤条件

[英]Rails Elasticsearch - multiple filter terms

我有一个模型Campaign,可以由类型为“ NonProfit”和“ Individual”的用户创建。

现在,我要搜索仅由非营利组织或个人或由任何一个组织创建的广告系列。

这是我的模型:

class Campaign < ActiveRecord::Base
after_commit lambda { __elasticsearch__.index_document  },  on: :create
after_commit lambda { __elasticsearch__.update_document },  on: :update

belongs_to :user

enum status: { waiting: 0, approved: 1, disapproved: 2, expired: 3, canceled: 4, draft: 5, published: 6}


def user_type
   self.user.rolable_type
end

def as_json(options={})
  super(:only => [:id, :status, :title, :description],
        :methods => [:user_type])
end

settings index: {
number_of_shards: 1,
analysis: {
  filter: {
    trigrams_filter: {
      type: 'ngram',
      min_gram: 2,
      max_gram: 10
    },
    content_filter: {
      type: 'ngram',
      min_gram: 4,
      max_gram: 20
    }
  },
  analyzer: {
    index_trigrams_analyzer: {
      type: 'custom',
      tokenizer: 'standard',
      filter: ['lowercase', 'trigrams_filter', 'asciifolding']
    },
    search_trigrams_analyzer: {
      type: 'custom',
      tokenizer: 'whitespace',
      filter: ['lowercase']
    },
    english: {
      tokenizer: 'standard',
      filter: ['standard', 'lowercase', 'content_filter']
    },
    czech: {
      tokenizer: 'standard',
      filter: ['standard','lowercase','content_filter', 'asciifolding']
    }
  }
}
} do
mappings dynamic: 'false' do
  indexes :status, type: 'string'
  indexes :user_type, type: 'string'
  indexes :en_title, index_analyzer: 'english', search_analyzer: 'english'
  indexes :ma_title, index_analyzer: 'czech', search_analyzer: 'czech'
  indexes :cs_title, index_analyzer: 'czech', search_analyzer: 'czech'
  indexes :en_description, index_analyzer: 'english', search_analyzer: 'english'
  indexes :ma_description, index_analyzer: 'czech', search_analyzer: 'czech'
  indexes :cs_description, index_analyzer: 'czech', search_analyzer: 'czech'
end
end

  def as_indexed_json(options={})
{ id: id,
  status: status,
  user_type: user_type,
  ma_title: ma_title,
  cs_title: cs_title,
  en_title: en_title,
  ma_description: ma_description,
  cs_description: cs_description,
  en_description: en_description  
}
  end

   def self.search(query, user_type)
__elasticsearch__.search(
  {
    query: {
      filtered: {
        query: {
          multi_match: {
            query: query,
            fields: ['ma_title^10', 'cs_title^10', 'en_title^10', 'ma_description', 'cs_description', 'en_description']
          }
        },
        filter: {
          term: {
            status: "published"               
          },
          term: {
            user_type: user_type
          }
        }
      }
    }       
  }
)
 end

end

我的控制器看起来像这样:

Campaign.search(params[:q], 'NonProfit') # to search only NonProfit campaigns
Campaign.search(params[:q], 'Individual') # to search only Individual campaigns
Campaign.search(params[:q], ['NonProfit','Individual']) # to search any of the campaigns

但是我总是得到0个结果。 删除过滤条件“ user_type”时,我的工作效果很好。 我无法使user_type过滤器术语按预期工作。

任何想法,如何使其工作? 谢谢,米罗斯拉夫

UPDATE 1(过滤器user_type仍然不起作用-0个结果):

def as_json(options={})
  super(:only => [:id, :status, :title, :description],
        :methods => [:user_type]
     #   :include => {
     #     :employers => {:only => [:title]},
     #     :roles => {:only => [:name]}
     #   }
  )
end

settings index: {
number_of_shards: 1,
analysis: {
  filter: {
    trigrams_filter: {
      type: 'ngram',
      min_gram: 2,
      max_gram: 10
    },
    content_filter: {
      type: 'ngram',
      min_gram: 4,
      max_gram: 20
    }
  },
  analyzer: {
    index_trigrams_analyzer: {
      type: 'custom',
      tokenizer: 'standard',
      filter: ['lowercase', 'trigrams_filter', 'asciifolding']
    },
    search_trigrams_analyzer: {
      type: 'custom',
      tokenizer: 'whitespace',
      filter: ['lowercase']
    },
    english: {
      tokenizer: 'standard',
      filter: ['standard', 'lowercase', 'content_filter']
    },
    czech: {
      tokenizer: 'standard',
      filter: ['standard','lowercase','content_filter', 'asciifolding']
    }
  }
}
} do
mappings dynamic: 'false' do
  indexes :status, type: 'string', index: 'not_analyzed'
  indexes :user_type, type: 'string', index: 'not_analyzed'
  indexes :en_title, index_analyzer: 'english', search_analyzer: 'english'
  indexes :ma_title, index_analyzer: 'czech', search_analyzer: 'czech'
  indexes :cs_title, index_analyzer: 'czech', search_analyzer: 'czech'
  indexes :en_description, index_analyzer: 'english', search_analyzer: 'english'
  indexes :ma_description, index_analyzer: 'czech', search_analyzer: 'czech'
  indexes :cs_description, index_analyzer: 'czech', search_analyzer: 'czech'
end
end

def as_indexed_json(options={})
{ id: id,
  status: status,
  ma_title: ma_title,
  cs_title: cs_title,
  en_title: en_title,
  ma_description: ma_description,
  cs_description: cs_description,
  en_description: en_description,
  :methods => [:user_type]
}
end




def self.search(query, user_type)
__elasticsearch__.search(
  {
    query: {
      filtered: {
        query: {
          multi_match: {
            query: query,
            fields: ['ma_title^10', 'cs_title^10', 'en_title^10', 'ma_description', 'cs_description', 'en_description']
          }
        },
        filter: {
          bool: {
            must: [
              {
                term: {
                  status: "published"
                }
              },
              {
                terms: {
                  user_type: user_type
                }
              }
            ]
          }
        }
      }
    }       
  }
)
end

您需要在字段statususer_type mapping添加"index" : "not_analyzed" 由于您未指定任何分析器,因此ES在这些字段中使用了standard analyzer

mappings dynamic: 'false' do
  indexes :status, type: 'string', index : 'not_analyzed' <--- here
  indexes :user_type, type: 'string', index : 'not_analyzed' <--- here

如果需要使用术语过滤器,则由于term queries不执行任何分析,因此需要确保其完全匹配。

同样对于Campaign.search(params[:q], ['NonProfit','Individual']) # to search any of the campaigns都需要使用术语过滤器

编辑 条款查询

字词查询期望值数组

Campaign.search(params[:q], ['NonProfit'])

尝试这个

{
   "terms": {
      "user_type": ['NonProfit']
   }
 }

我希望这有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM