Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

indexers

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

indexers

  • 5.1.1
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

Gem Version Code Climate Build Status Dependency Status

Indexers

Dsl to delegate searches to elasticsearch in rails.

Why

I did this gem to:

  • Gain control of the queries without losing simplicity.
  • Have out of the box integration with activerecord and pagers.
  • Deal with the just in time nature of elasticsearch.
  • Integrate activerecord includes on it.
  • Have a convention of how to use suggestions.

Install

Put this line in your Gemfile:

gem 'indexers'

Then bundle:

$ bundle

To install Redis you can use homebrew:

$ brew install elasticsearch

NOTE: This gem is tested agains version 5.4.

Configuration

Generate the configuration file:

$ bundle exec rails g indexers:install

Set the global settings:

Indexers.configure do |config|

  config.mappings do
    name do
      type 'string'
      fields do
        raw do
          type 'keyword'
        end
      end
    end
    category type: 'string'
    price type: 'long'
    currency type: 'string'
    product_suggestions do
      type 'completion'
      analyzer 'simple'
    end
  end

end

If you need to personalize the analysis:

Indexers.configure do |config|

  config.analysis do
    filter do
      ngram do
        type 'nGram'
        min_gram 2
        max_gram 20
      end
    end
    analyzer do
      ngram do
        type 'custom'
        tokenizer 'standard'
        filter %w(lowercase ngram)
      end
    end
  end

end

NOTE: You may want to personalize the generated config/elasticsearch.yml.

Definitions

Generate an index:

$ bundle exec rails g indexers:indexer products

Define the mappings, serialization and search in the index:

Indexers.define :product do

  mappings do
    properties :name, :category, :price, :product_suggestions
  end

  serialize do |record|
    extract record, :name, :category, :price
    product_suggestions do
      input [record.name, transliterate(record.name)].uniq
    end
  end

  search do |*args|
    options = args.extract_options!
    term = args.first
    query do
      if term.present?
        multi_match do
          query term
          type 'phrase_prefix'
          fields %w(name category)
        end
      else
        match_all
      end
    end
  end

end

Traits

You can dry complex searches or serializations using traits:

Indexers.define :product do

  search do |*args|
    options = args.extract_options!
    shop = options[:shop]
    term = args.first
    query do
      bool do
        must do
          if term.present?
            multi_match do
              query term
              type 'phrase_prefix'
              fields %w(name category)
            end
          else
            match_all
          end
        end
        traits :shop
      end
    end
  end

  trait :shop do
    filter do
      if shop
        term do
          _parent shop.id
        end
      end
    end
  end

end

NOTE: The binding is persisted, there is no need to redefine variables.

Indexing

The index will be updated every time a record is created, updated or destroyed:

product = Product.create(name: 'Les Paul', category: 'Gibson')

You can force this actions manually with:

product.index
product.reindex
product.unindex

Rake tasks

At any time you can build/rebuild your indexers using:

$ bundle exec rake indexers:index
$ bundle exec rake indexers:reindex
$ bundle exec rake indexers:unindex

Use the included search method in the model:

products = Product.search('Les Paul')

The result can be used as a collection in views:

<%= render products %>

Includes

Similar to using activerecod:

Product.search.includes(:shop)

Pagination

Works the same as pagers gem:

Products.search.page(1, padding: 4, length: 30)

You can force a record to be part of the results by id:

Products.search.page(1, with: 4)

Or the opposite:

Products.search.page(4, without: 4)

And you can send the collection directly to the view helper:

<%= paginate products %>

Order

Same as using activerecord:

Product.search.order(name: :asc)

You can use a computed sort by declare it in the configuration:

Indexers.configure do |config|

  config.computed_sort :price do |direction|
    type 'number'
    script do
      inline "if (params['_source']['currency'] == 'UYU') { doc['price'].value * 30 }"
    end
    order direction
  end

end

Suggestions

You need to first define the logic in the configuration:

Indexers.configure do |config|

  config.suggestions do |name, term, options={}|
    type = name.to_s.singularize
    text (term || '')
    completion do
      field "#{type}_suggestions"
    end
  end

end

Then you can get suggestions using the suggest method:

Indexers.suggest :product, 'gibson'

The result is an array of hashes with a text property:

[{ text: 'Les Paul' }, ...]

Contributing

Any issue, pull request, comment of any kind is more than welcome!

I will mainly ensure compatibility to Rails, AWS, PostgreSQL, Redis, Elasticsearch and FreeBSD. 

Credits

This gem is maintained and funded by museways.

License

It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.

FAQs

Package last updated on 07 Nov 2017

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc