artsy/estella

Name: estella

Owner: Artsy

Description: Make your Ruby objects searchable with Elasticsearch.

Created: 2017-01-12 10:57:51.0

Updated: 2017-10-13 21:06:47.0

Pushed: 2017-02-28 17:13:49.0

Homepage: null

Size: 55

Language: Ruby

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

estella

Gem Version Build Status License Status Coverage Status

Builds on elasticsearch-model to make your Ruby objects searchable with Elasticsearch. Provides fine-grained control of fields, analysis, filters, weightings and boosts.

Compatibility

This library is compatible with Elasticsearch 1.5.x, 2.x and currently does not work with Elasticsearch 5.x (see #18). It works with many ORM/ODMs, including ActiveRecord and Mongoid.

Dependencies
Installation
'estella'

Estella will try to use Elasticsearch on localhost:9200 by default.

You can configure your global ElasticSearch client like so:

ticsearch::Model.client = Elasticsearch::Client.new host: 'foo.com', log: true

It's also configurable on a per-model basis. Refer to the ElasticSearch documentation for details.

Indexing

Include the Estella::Searchable module and add a searchable block in your model declaring the fields to be indexed.

s Artist < ActiveRecord::Base
clude Estella::Searchable

archable do
field :name, type: :string, analysis: Estella::Analysis::FULLTEXT_ANALYSIS, factor: 1.0
field :keywords, type: :string, analysis: ['snowball', 'shingle'], factor: 0.5
field :bio, using: :biography, type: :string, index: :not_analyzed
field :birth_date, type: :date
field :follows, type: :integer
field :published, type: :boolean, filter: true
boost :follows, modifier: 'log1p', factor: 1E-3
d

For a full list of the options available for field mappings, see the ElasticSearch mapping documentation.

The filter option allows the field to be used as a filter at search time.

You can optionally provide field weightings to be applied at search time using the factor option. These are multipliers.

Document-level boosts can be applied with the boost declaration, see the field_value_factor documentation for boost options.

While filter, boost and factor are query options, Estella allows for their static declaration in the searchable block for simplicity - they will be applied at query time by default when using #estella_search.

You can now create your index mappings with this migration:

st.reload_index!

This uses a default index naming scheme based on your model name, which you can override simply by declaring the following in your model:

x_name 'my_index_name'

Start indexing documents simply by creating or saving them:

st.create(name: 'Frank Estella', keywords: ['art', 'minimalism'])

Estella adds after_save and after_destroy callbacks for inline indexing, override these callbacks if you'd like to do your indexing in a background process. For example:

s Artist < ActiveRecord::Base
clude Estella::Searchable

disable estella inline callbacks
ip_callback(:save, :after, :es_index)
ip_callback(:destroy, :after, :es_delete)

declare your own
ter_save :delay_es_index
ter_destroy :delay_es_delete

.

A number of class methods are available for indexing.

turn true if the index exists
st.index_exists?

eate the index
st.create_index!

lete and re-create the index without reindexing data
st.reload_index!

create the index and reindex all data
st.recreate_index!

lete the index
st.delete_index!

mmit any outstanding writes
st.refresh_index!
Custom Analysis

Estella defines standard, snowball, ngram and shingle analyzers by default. These cover most search contexts, including auto-suggest. In order to enable full-text search for a field, use:

ysis: Estella::Analysis::FULLTEXT_ANALYSIS

Or alternatively select your analysis by listing the analyzers you want enabled for a given field:

d :keywords, type: :string, analysis: ['snowball', 'shingle']

Estella default analyzer and sharding options are defined here and can be customized by passing a settings hash to the searchable block.

nalysis = {
kenizer: {
...

lter: {
...



ettings = {
alysis: my_analysis,
dex: {
number_of_shards: 1,
number_of_replicas: 1



chable my_settings do
.

See configuring analyzers for more information.

Searching

Perform full-text search with estella_search:

st.estella_search(term: 'frank')
st.estella_search(term: 'minimalism')

Estella searches all analyzed text fields by default, using a multi_match search. The search will return an array of database records, ordered by score. If you'd like access to the raw Elasticsearch response data use the raw option:

st.estella_search(term: 'frank', raw: true)

Estella supports filtering on filter fields and pagination:

st.estella_search(term: 'frank', published: true)
st.estella_search(term: 'frank', size: 10, from: 5)

You can exclude records:

st.estella_search(term: 'frank', exclude: { keywords: 'sinatra' })

If you'd like to customize your term query further, you can extend Estella::Query and override query_definition and field_factors:

s MyQuery < Estella::Query
f query_definition
{
  multi_match: {
    ...
  }
}
d

f field_factors
{
  default: 5,
  ngram: 5,
  snowball: 2,
  shingle: 1,
  search: 1
}
d

Or manipulate the query for all cases (with or without term) in the initializer directly via query or by using built-in helpers must and exclude.

s MyQuery < Estella::Query
f initialize(params)
super
# same as query[:filter][:bool][:must] = { keywords: 'frank' }
must(term: { keywords: 'frank' })
# same as query[:filter][:bool][:must_not] = { keywords: 'sinatra' }
exclude(term: { keywords: 'sinatra' })
d

And then override class method estella_search_query to direct Estella to use your query object:

s Artist < ActiveRecord::Base
clude Estella::Searchable

archable do
...
d

f self.estella_search_query
MyQuery
d


st.estella_search(term: 'frank')

For further search customization, see the ElasticSearch DSL.

Contributing

See CONTRIBUTING.

License

MIT License. See LICENSE.


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.