Module: SearchFlip::PostFilterable

Included in:
Criteria
Defined in:
lib/search_flip/post_filterable.rb

Overview

The SearchFlip::PostFilterable 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


23
24
25
26
27
# File 'lib/search_flip/post_filterable.rb', line 23

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

Instance Method Details

#post_exists(field) ⇒ SearchFlip::Criteria

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

Examples:

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

Parameters:

  • field (Symbol, String)

    The field that should have a non-null value

Returns:


230
231
232
# File 'lib/search_flip/post_filterable.rb', line 230

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

#post_exists_not(field) ⇒ SearchFlip::Criteria

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

Examples:

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

Parameters:

  • field (Symbol, String)

    The field that should have a null value

Returns:


245
246
247
# File 'lib/search_flip/post_filterable.rb', line 245

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

#post_filter(clause) ⇒ SearchFlip::Criteria

Adds raw post filter queries to the criteria.

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") }})

Parameters:

  • args (Array, Hash)

    The raw filter query arguments

Returns:


134
135
136
137
138
# File 'lib/search_flip/post_filterable.rb', line 134

def post_filter(clause)
  fresh.tap do |criteria|
    criteria.post_filter_values = (post_filter_values || []) + Helper.wrap_array(clause)
  end
end

#post_must(clause) ⇒ SearchFlip::Criteria

Adds raw post must queries to the criteria.

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") }})

Parameters:

  • args (Array, Hash)

    The raw must query arguments

Returns:


154
155
156
157
158
# File 'lib/search_flip/post_filterable.rb', line 154

def post_must(clause)
  fresh.tap do |criteria|
    criteria.post_must_values = (post_must_values || []) + Helper.wrap_array(clause)
  end
end

#post_must_not(clause) ⇒ SearchFlip::Criteria

Adds raw post must_not queries to the criteria.

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") }})

Parameters:

  • args (Array, Hash)

    The raw must_not query arguments

Returns:


174
175
176
177
178
# File 'lib/search_flip/post_filterable.rb', line 174

def post_must_not(clause)
  fresh.tap do |criteria|
    criteria.post_must_not_values = (post_must_not_values || []) + Helper.wrap_array(clause)
  end
end

#post_range(field, options = {}) ⇒ SearchFlip::Criteria

Adds a post range filter to the criteria 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)

Parameters:

  • field (Symbol, String)

    The field name to specify the range for

  • options (Hash) (defaults to: {})

    The range filter specification, like lt, lte, etc

Returns:


215
216
217
# File 'lib/search_flip/post_filterable.rb', line 215

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

#post_search(q, options = {}) ⇒ SearchFlip::Criteria

Adds a post query string query to the criteria 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*")

Parameters:

  • q (String)

    The query string query

  • options (Hash) (defaults to: {})

    Additional options for the query string query, like eg default_operator, default_field, etc.

Returns:


43
44
45
46
47
# File 'lib/search_flip/post_filterable.rb', line 43

def post_search(q, options = {})
  return self if q.to_s.strip.length.zero?

  post_must(query_string: { query: q, default_operator: :AND }.merge(options))
end

#post_should(clause) ⇒ SearchFlip::Criteria

Adds a raw post should query to the criteria.

Examples:

Raw post term should query

query = CommentIndex.aggregate("...")
query = query.post_should([
  { term: { state: "new" } },
  { term: { state: "approved" } }
])

Parameters:

  • clauses (Array)

    The raw should query arguments

Returns:


193
194
195
# File 'lib/search_flip/post_filterable.rb', line 193

def post_should(clause)
  post_must(bool: { should: clause })
end

#post_where(hash) ⇒ SearchFlip::Criteria

Adds post filters to your criteria 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")

Parameters:

  • hash (Hash)

    A field-to-filter mapping specifying filter values for the respective fields

Returns:


71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/search_flip/post_filterable.rb', line 71

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 } })
    elsif value.nil?
      memo.post_must_not(exists: { field: key })
    else
      memo.post_filter(term: { key => value })
    end
  end
end

#post_where_not(hash) ⇒ SearchFlip::Criteria

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")

Parameters:

  • hash (Hash)

    A field-to-filter mapping specifying filter values for the respective fields

Returns:


106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/search_flip/post_filterable.rb', line 106

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 } })
    elsif value.nil?
      memo.post_filter(exists: { field: key })
    else
      memo.post_must_not(term: { key => value })
    end
  end
end