<commit_before>module Searchkick
  class Index
    attr_reader :name, :options

    def initialize(name, options = {})
      @name = name
      @options = options
    end

    def create(options = {})
      client.indices.create index: name, body: options
    end

    def delete
      client.indices.delete index: name
    end

    def exists?
      client.indices.exists index: name
    end

    def refresh
      client.indices.refresh index: name
    end

    def alias_exists?
      client.indices.exists_alias name: name
    end

    def swap(new_name)
      old_indices =
        begin
          client.indices.get_alias(name: name).keys
        rescue Elasticsearch::Transport::Transport::Errors::NotFound
          []
        end
      actions = old_indices.map{|old_name| {remove: {index: old_name, alias: name}} } + [{add: {index: new_name, alias: name}}]
      client.indices.update_aliases body: {actions: actions}
    end

    # record based

    def store(record)
      client.index(
        index: name,
        type: document_type(record),
        id: search_id(record),
        body: search_data(record)
      )
    end

    def remove(record)
      client.delete(
        index: name,
        type: document_type(record),
        id: search_id(record)
      )
    end

    def import(records)
      records.group_by{|r| document_type(r) }.each do |type, batch|
        client.bulk(
          index: name,
          type: type,
          body: batch.map{|r| {index: {_id: search_id(r), data: search_data(r)}} }
        )
      end
    end

    def retrieve(record)
      client.get(
        index: name,
        type: document_type(record),
        id: record.id
      )["_source"]
    end

    def reindex_record(record)
      if record.destroyed? or !record.should_index?
        begin
          remove(record)
        rescue Elasticsearch::Transport::Transport::Errors::NotFound
          # do nothing
        end
      else
        store(record)
      end
    end

    def reindex_record_async(record)
      if defined?(Searchkick::ReindexV2Job)
          Searchkick::ReindexV2Job.perform_later(record.class.name, record.id.to_s)
      else
        Delayed::Job.enqueue Searchkick::ReindexJob.new(record.class.name, record.id.to_s)
      end
    end

    def similar_record(record, options = {})
      like_text = record.search_data
        .keep_if{|k,v| !options[:fields] || options[:fields].include?(k) }
        # .values.compact.join(" ")

      # TODO deep merge method
      options[:where] ||= {}
      options[:where][:_id] ||= {}
      options[:where][:_id][:not] = record.id.to_s
      options[:limit] ||= 10
      options[:similar] = true

      options[:like_text] = like_text
      like_text = like_text.map{|k,v| "#{v}" }.compact.join(" ")
      
      # TODO use index class instead of record class
      search_model(record.class, like_text, options)
    end

    # search

    def search_model(searchkick_klass, term = nil, options = {}, &block)
      query = Searchkick::Query.new(searchkick_klass, term, options)
      if block
        block.call(query.body)
      end
      if options[:execute] == false
        query
      else
        query.execute
      end
    end

    def count_model(searchkick_klass, term = nil, options = {})
      search_model(searchkick_klass, term, options.merge(search_type: "count")).total_count
    end

    def msearch_model(searchkick_klass, args = [])
      queries = args.map { |term, options| search_model(searchkick_klass, temp, options.merge(execute: false)) }<commit_msg>for Latta and Uzza, what a typo ._.<commit_after>module Searchkick
  class Index
    attr_reader :name, :options

    def initialize(name, options = {})
      @name = name
      @options = options
    end

    def create(options = {})
      client.indices.create index: name, body: options
    end

    def delete
      client.indices.delete index: name
    end

    def exists?
      client.indices.exists index: name
    end

    def refresh
      client.indices.refresh index: name
    end

    def alias_exists?
      client.indices.exists_alias name: name
    end

    def swap(new_name)
      old_indices =
        begin
          client.indices.get_alias(name: name).keys
        rescue Elasticsearch::Transport::Transport::Errors::NotFound
          []
        end
      actions = old_indices.map{|old_name| {remove: {index: old_name, alias: name}} } + [{add: {index: new_name, alias: name}}]
      client.indices.update_aliases body: {actions: actions}
    end

    # record based

    def store(record)
      client.index(
        index: name,
        type: document_type(record),
        id: search_id(record),
        body: search_data(record)
      )
    end

    def remove(record)
      client.delete(
        index: name,
        type: document_type(record),
        id: search_id(record)
      )
    end

    def import(records)
      records.group_by{|r| document_type(r) }.each do |type, batch|
        client.bulk(
          index: name,
          type: type,
          body: batch.map{|r| {index: {_id: search_id(r), data: search_data(r)}} }
        )
      end
    end

    def retrieve(record)
      client.get(
        index: name,
        type: document_type(record),
        id: record.id
      )["_source"]
    end

    def reindex_record(record)
      if record.destroyed? or !record.should_index?
        begin
          remove(record)
        rescue Elasticsearch::Transport::Transport::Errors::NotFound
          # do nothing
        end
      else
        store(record)
      end
    end

    def reindex_record_async(record)
      if defined?(Searchkick::ReindexV2Job)
          Searchkick::ReindexV2Job.perform_later(record.class.name, record.id.to_s)
      else
        Delayed::Job.enqueue Searchkick::ReindexJob.new(record.class.name, record.id.to_s)
      end
    end

    def similar_record(record, options = {})
      like_text = record.search_data
        .keep_if{|k,v| !options[:fields] || options[:fields].include?(k) }
        # .values.compact.join(" ")

      # TODO deep merge method
      options[:where] ||= {}
      options[:where][:_id] ||= {}
      options[:where][:_id][:not] = record.id.to_s
      options[:limit] ||= 10
      options[:similar] = true

      options[:like_text] = like_text
      like_text = like_text.map{|k,v| "#{v}" }.compact.join(" ")
      
      # TODO use index class instead of record class
      search_model(record.class, like_text, options)
    end

    # search

    def search_model(searchkick_klass, term = nil, options = {}, &block)
      query = Searchkick::Query.new(searchkick_klass, term, options)
      if block
        block.call(query.body)
      end
      if options[:execute] == false
        query
      else
        query.execute
      end
    end

    def count_model(searchkick_klass, term = nil, options = {})
      search_model(searchkick_klass, term, options.merge(search_type: "count")).total_count
    end

    def msearch_model(searchkick_klass, args = [])
      queries = args.map { |term, options| search_model(searchkick_klass, term, options.merge(execute: false)) }
{'fraction_non_alphanumeric': 0.11321548821548821, 'fraction_numerical': 0.001122334455667789, 'mean_word_length': 2.346948356807512, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '5865151', 'n_tokens_mistral': 2223, 'n_tokens_neox': 2166, 'n_words': 491}