Module: ElasticSearch::PostFilterableRelation

Included in:
Relation
Defined in:
lib/elastic_search/post_filterable_relation.rb

Overview

The ElasticSearch::PostFilterableRelation mixin provides chainable methods like #post_where, #post_exists, #post_range, etc to add and apply search filters after aggregations have already been calculated.

Examples:

query = ProductIndex.search("harry potter")

query = query.aggregate(price_ranges: {
  range: {
    field: "price",
    ranges: [
      { key: "range1", from: 0,  to: 20 },
      { key: "range2", from: 20, to: 50 },
      { key: "range3", from: 50, to: 100 }
    ]
  }
})

query = query.post_where(price: 20 ... 50)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



24
25
26
27
28
# File 'lib/elastic_search/post_filterable_relation.rb', line 24

def self.included(base)
  base.class_eval do
    attr_accessor :post_search_values, :post_must_values, :post_must_not_values, :post_should_values, :post_filter_values
  end
end

Instance Method Details

#post_exists(field) ⇒ ElasticSearch::Relation

Adds a post exists filter to the relation, which selects all documents for which the specified field has a non-null value.

Examples:

query = CommentIndex.aggregate("...")
query = query.post_exists(:notified_at)


232
233
234
# File 'lib/elastic_search/post_filterable_relation.rb', line 232

def post_exists(field)
  post_filter exists: { field: field }
end

#post_exists_not(field) ⇒ ElasticSearch::Relation

Adds a post exists not filter to the relation, which selects all documents for which the specified field's value is null.

Examples:

query = CommentIndex.aggregate("...")
query = query.post_exists_not(:notified_at)


247
248
249
# File 'lib/elastic_search/post_filterable_relation.rb', line 247

def post_exists_not(field)
  post_must_not exists: { field: field }
end

#post_filter(*args) ⇒ ElasticSearch::Relation

Adds raw post filter queries to the relation.

Examples:

Raw post term filter query

query = CommentIndex.aggregate("...")
query = query.post_filter(term: { state: "new" })

Raw post range filter query

query = CommentIndex.aggregate("...")
query = query.post_filter(range: { created_at: { gte: Time.parse("2016-01-01") }})


133
134
135
136
137
# File 'lib/elastic_search/post_filterable_relation.rb', line 133

def post_filter(*args)
  fresh.tap do |relation|
    relation.post_filter_values = (post_filter_values || []) + args
  end
end

#post_must(*args) ⇒ ElasticSearch::Relation

Adds raw post must queries to the relation.

Examples:

Raw post term must query

query = CommentIndex.aggregate("...")
query = query.post_must(term: { state: "new" })

Raw post range must query

query = CommentIndex.aggregate("...")
query = query.post_must(range: { created_at: { gte: Time.parse("2016-01-01") }})


153
154
155
156
157
# File 'lib/elastic_search/post_filterable_relation.rb', line 153

def post_must(*args)
  fresh.tap do |relation|
    relation.post_must_values = (post_must_values || []) + args
  end
end

#post_must_not(*args) ⇒ ElasticSearch::Relation

Adds raw post must_not queries to the relation.

Examples:

Raw post term must_not query

query = CommentIndex.aggregate("...")
query = query.post_must_not(term: { state: "new" })

Raw post range must_not query

query = CommentIndex.aggregate("...")
query = query.post_must_not(range: { created_at: { gte: Time.parse("2016-01-01") }})


173
174
175
176
177
# File 'lib/elastic_search/post_filterable_relation.rb', line 173

def post_must_not(*args)
  fresh.tap do |relation|
    relation.post_must_not_values = (post_must_not_values || []) + args
  end
end

#post_range(field, options = {}) ⇒ ElasticSearch::Relation

Adds a post range filter to the relation without being forced to specify the left and right end of the range, such that you can eg simply specify lt, lte, gt and gte. For fully specified ranges, you can easily use #post_where, etc. Check out the ElasticSearch docs for further details regarding the range filter.

Examples:

query = CommentIndex.aggregate("...")
query = query.post_range(:created_at, gte: Time.parse("2016-01-01"))

query = CommentIndex.aggregate("...")
query = query.post_range(:likes_count, gt: 10, lt: 100)


217
218
219
# File 'lib/elastic_search/post_filterable_relation.rb', line 217

def post_range(field, options = {})
  post_filter range: { field => options }
end

#post_search(q, options = {}) ⇒ ElasticSearch::Relation

Adds a post query string query to the relation while using AND as the default operator unless otherwise specified. Check out the ElasticSearch docs for further details.

Examples:

CommentIndex.aggregate(:user_id).post_search("message:hello OR message:worl*")

Raises:



44
45
46
47
48
49
50
# File 'lib/elastic_search/post_filterable_relation.rb', line 44

def post_search(q, options = {})
  raise(ElasticSearch::NotSupportedError) if ElasticSearch.version.to_i < 2

  fresh.tap do |relation|
    relation.post_search_values = (post_search_values || []) + [query_string: { query: q, :default_operator => :AND }.merge(options)] if q.to_s.strip.length > 0
  end
end

#post_should(*args) ⇒ ElasticSearch::Relation

Adds raw post should queries to the relation.

Examples:

Raw post term should query

query = CommentIndex.aggregate("...")
query = query.post_should(term: { state: "new" })

Raw post range should query

query = CommentIndex.aggregate("...")
query = query.post_should(range: { created_at: { gte: Time.parse("2016-01-01") }})


193
194
195
196
197
# File 'lib/elastic_search/post_filterable_relation.rb', line 193

def post_should(*args)
  fresh.tap do |relation|
    relation.post_should_values = (post_should_values || []) + args
  end
end

#post_where(hash) ⇒ ElasticSearch::Relation

Adds post filters to your relation for the supplied hash composed of field-to-filter mappings which specify terms, term or range filters, depending on the type of the respective hash value, namely array, range or scalar type like Fixnum, String, etc.

Examples:

Array values

query = CommentIndex.aggregate("...")
query = query.post_where(id: [1, 2, 3], state: ["approved", "declined"])

Range values

query = CommentIndex.aggregate("...")
query = query.post_where(created_at: Time.parse("2016-01-01") .. Time.parse("2017-01-01"))

Scalar types

query = CommentIndex.aggregate("...")
query = query.post_where(id: 1, message: "hello world")


74
75
76
77
78
79
80
81
82
83
84
# File 'lib/elastic_search/post_filterable_relation.rb', line 74

def post_where(hash)
  hash.inject(fresh) do |memo, (key, value)|
    if value.is_a?(Array)
      memo.post_filter terms: { key => value }
    elsif value.is_a?(Range)
      memo.post_filter range: { key => { gte: value.min, lte: value.max } }
    else
      memo.post_filter term: { key => value }
    end
  end
end

#post_where_not(hash) ⇒ ElasticSearch::Relation

Adds post filters to exclude documents in accordance to the supplied hash composed of field-to-filter mappings. Check out #post_where for further details.

Examples:

Array values

query = CommentIndex.aggregate("...")
query = query.post_where_not(id: [1, 2, 3])

Range values

query = CommentIndex.aggregate("...")
query = query.post_where_not(created_at: Time.parse("2016-01-01") .. Time.parse("2017-01-01"))
query = CommentIndex.aggregate("...")
query = query.post_where_not(state: "approved")


107
108
109
110
111
112
113
114
115
116
117
# File 'lib/elastic_search/post_filterable_relation.rb', line 107

def post_where_not(hash)
  hash.inject(fresh) do |memo, (key,value)|
    if value.is_a?(Array)
      memo.post_must_not terms: { key => value }
    elsif value.is_a?(Range)
      memo.post_must_not range: { key => { gte: value.min, lte: value.max } }
    else
      memo.post_must_not term: { key => value }
    end
  end
end