<commit_before>module SearchFlip
  # 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("<NAME>")
  #
  #   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)

  module PostFilterable
    def self.included(base)
      base.class_eval do
        attr_accessor :post_must_values, :post_must_not_values, :post_filter_values
      end
    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

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

      return self if q.to_s.strip.length.zero?

      post_must(query_string: { query: q, default_operator: :AND }.merge(options))
    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

    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

    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

    # 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

    def post_filter(clause, options = nil)
      return post_must(bool: options.merge(filter: clause)) if options

      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

    def post_must(clause, options = nil)
      return post_must(options.merge(must: clause)) if options

      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

    def post_must_not(clause, options = nil)
      return post_must(options.merge(must_not: clause)) if options

      fresh.tap do |criteria|
        criteria.post_must_not_values = (post_must_not_values || []) + Helper.wrap_array(clause)
      end
    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" } }
    #   ])<commit_msg>Remove options argument from post methods<commit_after>module SearchFlip
  # 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)

  module PostFilterable
    def self.included(base)
      base.class_eval do
        attr_accessor :post_must_values, :post_must_not_values, :post_filter_values
      end
    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

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

      return self if q.to_s.strip.length.zero?

      post_must(query_string: { query: q, default_operator: :AND }.merge(options))
    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

    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

    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

    # 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

    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

    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

    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 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" } }
    #   ])
{'fraction_non_alphanumeric': 0.12164827938920143, 'fraction_numerical': 0.01212829692408855, 'mean_word_length': 2.579497907949791, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4209065', 'n_tokens_mistral': 4465, 'n_tokens_neox': 4292, 'n_words': 1172}