module SearchFlip::PostFilterable
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.
@example
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)
Public Class Methods
# 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
Public Instance Methods
Adds a post exists filter to the criteria, which selects all documents for which the specified field has a non-null value.
@example
query = CommentIndex.aggregate("...") query = query.post_exists(:notified_at)
@param field [Symbol, String] The field that should have a non-null value
@return [SearchFlip::Criteria] A newly created extended criteria
# File lib/search_flip/post_filterable.rb, line 230 def post_exists(field) post_filter(exists: { field: field }) end
Adds a post exists not query to the criteria, which selects all documents for which the specified field's value is null.
@example
query = CommentIndex.aggregate("...") query = query.post_exists_not(:notified_at)
@param field [Symbol, String] The field that should have a null value
@return [SearchFlip::Criteria] A newly created extended criteria
# File lib/search_flip/post_filterable.rb, line 245 def post_exists_not(field) post_must_not(exists: { field: field }) end
Adds raw post filter queries to the criteria.
@example Raw post term filter query
query = CommentIndex.aggregate("...") query = query.post_filter(term: { state: "new" })
@example Raw post range filter query
query = CommentIndex.aggregate("...") query = query.post_filter(range: { created_at: { gte: Time.parse("2016-01-01") }})
@param args [Array, Hash] The raw filter query arguments
@return [SearchFlip::Criteria] A newly created extended criteria
# 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
Adds raw post must queries to the criteria.
@example Raw post term must query
query = CommentIndex.aggregate("...") query = query.post_must(term: { state: "new" })
@example Raw post range must query
query = CommentIndex.aggregate("...") query = query.post_must(range: { created_at: { gte: Time.parse("2016-01-01") }})
@param args [Array, Hash] The raw must query arguments
@return [SearchFlip::Criteria] A newly created extended criteria
# 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
Adds raw post must_not queries to the criteria.
@example Raw post term must_not query
query = CommentIndex.aggregate("...") query = query.post_must_not(term: { state: "new" })
@example Raw post range must_not query
query = CommentIndex.aggregate("...") query = query.post_must_not(range: { created_at: { gte: Time.parse("2016-01-01") }})
@param args [Array, Hash] The raw must_not query arguments
@return [SearchFlip::Criteria] A newly created extended criteria
# 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
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.
@example
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)
@param field [Symbol, String] The field name to specify the range for @param options [Hash] The range filter specification, like lt, lte, etc
@return [SearchFlip::Criteria] A newly created extended criteria
# File lib/search_flip/post_filterable.rb, line 215 def post_range(field, options = {}) post_filter(range: { field => options }) end
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.
@example
CommentIndex.aggregate(:user_id).post_search("message:hello OR message:worl*")
@param q [String] The query string query
@param options [Hash] Additional options for the query string query, like
eg default_operator, default_field, etc.
@return [SearchFlip::Criteria] A newly created extended criteria
# 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
Adds a raw post should query to the criteria.
@example Raw post term should query
query = CommentIndex.aggregate("...") query = query.post_should([ { term: { state: "new" } }, { term: { state: "approved" } } ])
@param clauses [Array] The raw should query arguments
@return [SearchFlip::Criteria] A newly created extended criteria
# File lib/search_flip/post_filterable.rb, line 193 def post_should(clause) post_must(bool: { should: clause }) end
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.
@example Array values
query = CommentIndex.aggregate("...") query = query.post_where(id: [1, 2, 3], state: ["approved", "declined"])
@example Range values
query = CommentIndex.aggregate("...") query = query.post_where(created_at: Time.parse("2016-01-01") .. Time.parse("2017-01-01"))
@example Scalar types
query = CommentIndex.aggregate("...") query = query.post_where(id: 1, message: "hello world")
@param hash [Hash] A field-to-filter mapping specifying filter values for
the respective fields
@return [SearchFlip::Criteria] A newly created extended criteria
# 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
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.
@example Array values
query = CommentIndex.aggregate("...") query = query.post_where_not(id: [1, 2, 3])
@example Range values
query = CommentIndex.aggregate("...") query = query.post_where_not(created_at: Time.parse("2016-01-01") .. Time.parse("2017-01-01"))
@example
query = CommentIndex.aggregate("...") query = query.post_where_not(state: "approved")
@param hash [Hash] A field-to-filter mapping specifying filter values for the
respective fields
@return [SearchFlip::Criteria] A newly created extended criteria
# 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