如何使用elaticsearch和rails创建范围过滤器

时间:2016-06-24 19:21:46

标签: ruby-on-rails elasticsearch filter aggregation

我正在尝试在此link上为此rails应用添加范围聚合到运行时字段:

模型/ movie.rb:

def custom_search(query_segment)
  keyword         = query_segment.delete("keyword")
  range_segments   = query_segment.delete("runtimes")
  filter_segments = query_segment

  __elasticsearch__.search(query:  MoviesQuery.build(keyword),
                           aggs:   MoviesQuery::Aggregate.build, 
                           filter: MoviesQuery::Filter.build(filter_segments, range_segments))
end

movies_controller.rb

def segmented_query
  query.slice(*["crews", "keyword", "genres", "runtimes"]) rescue {}
end

movies_query.rb

module Filter
  def self.build(segments, range)
    { 
      bool: { 
        must: nested_terms_filter(segments, range)
      }
    }
  end

  def self.nested_terms_filter(segments, range)
    segments.keys.map do |path|
      if path == "runtimes"
        if range.split("-").count > 1
          {
              "range": {
                  "runtime": {
                      "gt": range.split('-').first,
                      "lt": range.split('-').last
                  }
              }
          }
        else
          {
              "range": {
                  "runtime": {
                      "gt": range
                  }
              }
          }
        end
      else
        {
            nested: {
                path: path,
                filter: {
                    terms: { "#{path}.id": segments[path].split(',').map(&:to_i) }
                }
            }
        }
      end
    end
  end
end

助手/ application_helper.rb

module ApplicationHelper
  def agg_name(va)
    if va.first(2) == '*-'
      "#{va.split('-').last.to_i} and below"
    elsif va.last(2) == '-*'
      "above #{va.split('-').first.to_i}"
    else
      s = va.split('-')
      [s.first.to_i, s.last.to_i].join(' to ')
    end
  end

  def agg_id(va)
    if va.first(2) == '*-'
      "0-#{va.split('-').last.to_i}"
    elsif va.last(2) == '-*'
      "#{va.split('-').first.to_i}"
    else
      s = va.split('-')
      [s.first.to_i, s.last.to_i].join('-')
    end
  end
end

演示/ aggregation_presenter.rb

def buckets
  if aggregation[1].id_and_name.present?
    aggregation[1].id_and_name.buckets.map{ |b| BucketPresenter.new(b) }
  end
end

视图/聚集/ aggregation.html.haml

%h3= agg.name
- if agg.buckets.present?
  %ul.nav.nav-pills.nav-stacked
    - agg.buckets.each do |bucket|
      = content_tag :li, class: aggregation_active?(agg.kind, bucket.id) do
        = link_to aggregation_path(agg.kind, bucket.id, :merge) do
          = bucket.name
          (#{bucket.count})
- else
  %ul.nav.nav-pills.nav-stacked
    - agg.aggregation[1]['buckets'].each do |bucket|
      = content_tag :li, class: aggregation_active?(agg.kind, agg_id(bucket['key']) ) do
        = link_to aggregation_path(agg.kind, agg_id(bucket['key']), :merge) do
          = agg_name(bucket['key'])
          (#{bucket.count})

传递此网址会给我:

段:

{"crews"=>"44631,112041", "genres"=>"19,1"}

范围:

"0-50,50-100"

为什么范围过滤器不起作用,哪里出错?

0 个答案:

没有答案