Elasticsearch::Resources

Build Status Gem Version

For Ruby 2.3+

Elasticsearch::Resources is a wrapper for the Elasticsearch gem that provides a strongly typed interface for accessing your indexes, types, and documents.

# Search an index: e.g. search { index: 'film', body: { query: { ... } } }
documents = film.search({ query: { match: { title: 'Tron' } } })
documents # [#<Movie @title='Tron'>, #<Documentary @title='Making Tron'>]

# Get a specific document: e.g. get { index: 'film', type: 'movies', id: 'tron' }
document = movies.get(id: 'tron') # #<Movie @title='Tron'>
document.id # => 'tron'
document.attributes # => { 'title' => 'Tron' }
document.title # => 'Tron'

Installation

If you're not using Bundler...

Install the gem via:

gem install elasticsearch-resources

Then require it into your application with:

require 'elasticsearch/resources'
If you're using Bundler...

Add the gem to your Gemfile:

gem 'elasticsearch/resources'

And then bundle install to install the gem and its dependencies.

Common use cases

Search all indexes in a cluster
# Connects to default of '127.0.0.1:9200'
cluster = Elasticsearch::Resources::Cluster.new

# Hash can be any valid Elasticsearch query
documents = cluster.search({ query: { match: { title: 'Tron' } } })
Search all types in an index
# Connects to default of '127.0.0.1:9200'
cluster = Elasticsearch::Resources::Cluster.new
documents = cluster.search({ index: 'film', query: { match: { title: 'Tron' } } })

# OR using a defined index
index = Elasticsearch::Resources::Index.new(cluster: cluster) do |index|
  index.name = 'film'
end

documents = index.search({ query: { match: { title: 'Tron' } } })
Search specific type in an index
# Connects to default of '127.0.0.1:9200'
cluster = Elasticsearch::Resources::Cluster.new
documents = cluster.search({ index: 'film', type: 'movies', query: { match: { title: 'Tron' } } })

# OR using a defined index & type
index = Elasticsearch::Resources::Index.new(cluster: cluster) do |index|
  index.name = 'film'
end

type = Elasticsearch::Resources::Type.new(index: index) do |type|
  type.name = 'movies'
end

documents = type.search({ query: { match: { title: 'Tron' } } })
Creating a document
# type: Elasticsearch::Resources::Type object
document = Elasticsearch::Resources::Document.new(type: type, id: 'tron', attributes: { title: 'Tron' })
document.create
Fetch a document
document = type.get(id: 'tron')

Resources

There are four (4) basic resources which you can query with: Cluster, Index, Type, and Document.

Cluster

An Elasticsearch::Resources::Cluster represents an ElasticSearch cluster that hosts multiple indexes. You will always needs to create one to run queries.

# Create a cluster with default settings (connects to '127.0.0.1:9200')
cluster = Elasticsearch::Resources::Cluster.new

# Create a cluster with custom host
cluster = Elasticsearch::Resources::Cluster.new do |cluster|
  cluster.host = 'davesawesomemovies.com:9200'
end
indexes

Returns a Hash of well known indexes. Empty if no well-known indexes are defined (regardless of whether they actually exist in Elasticsearch.) See "Defining well known resources" and define_indexes.

cluster.indexes
# => { film: #<Elasticsearch::Resources::Index> }
client

Returns the underlying Elasticsearch::Transport::Client.

cluster.client

Accepts (body, options = {}) and calls search on the Elasticsearch::Transport::Client.

Returns Array[Elasticsearch::Resources::Document] objects.

cluster.search({ query: { match: { title: 'Tron' } } })
# => [#<Elasticsearch::Resources::Document>]
count

Accepts (body, options = {}) and calls count on the Elasticsearch::Transport::Client.

Returns Hash response from Elasticsearch::Transport::Client.

cluster.count({ query: { match: { title: 'Tron' } } })
# => {"count"=>1, "_shards"=>{"total"=>5, "successful"=>5, "failed"=>0}}

Index

An Elasticsearch::Resources::Index represents an ElasticSearch index that contains multiple types. Requires a Cluster (see "Cluster" above.)

# Create an index. You must set `name`.
index = Elasticsearch::Resources::Index.new(cluster: cluster) do |index|
  index.name = 'film'
end
name

Returns the name of the index, as it exists in Elasticsearch.

index.name
# => 'film'
types

Returns a Hash of well known types. Empty if no well-known types are defined (regardless of whether they actually exist in Elasticsearch.) See "Defining well known resources" and define_types.

index.types
# => { movies: #<Elasticsearch::Resources::Type> }
client

Returns the underlying Elasticsearch::Transport::Client.

index.client

Accepts (body, options = {}) and calls search on the Elasticsearch::Transport::Client. Automatically adds the index option to your queries.

Returns Array[Elasticsearch::Resources::Document] objects.

index.search({ query: { match: { title: 'Tron' } } })
# => [#<Elasticsearch::Resources::Document>]
count

Accepts (body, options = {}) and calls count on the Elasticsearch::Transport::Client. Automatically adds the index option to your queries.

Returns Hash response from Elasticsearch::Transport::Client.

index.count({ query: { match: { title: 'Tron' } } })
# => {"count"=>1, "_shards"=>{"total"=>5, "successful"=>5, "failed"=>0}}
exists?

Calls exists? on the Elasticsearch::API::Indices::IndicesClient.

Returns true or false.

index.exists?
# => true
create

Calls create on the Elasticsearch::API::Indices::IndicesClient.

Throws error if index already exists.

index.create
put_mapping

Accepts (options = {}) and calls put_mapping on the Elasticsearch::API::Indices::IndicesClient.

index.put_mapping(type: 'movies', body: { })
delete

Calls delete on the Elasticsearch::API::Indices::IndicesClient.

Throws error if index doesn't exist.

index.delete

Type

An Elasticsearch::Resources::Type represents an ElasticSearch type within an index. Requires a Index (see "Index" above.)

# Create a type. You must set `name`.
type = Elasticsearch::Resources::Type.new(index: index) do |type|
  type.name = 'movie'
end
name

Returns the name of the type, as it exists in Elasticsearch.

type.name
# => 'movie'
client

Returns the underlying Elasticsearch::Transport::Client.

type.client

Accepts (body, options = {}) and calls search on the Elasticsearch::Transport::Client. Automatically adds the index and type option to your queries.

Returns Array[Elasticsearch::Resources::Document] objects.

type.search({ query: { match: { title: 'Tron' } } })
# => [#<Elasticsearch::Resources::Document>]
count

Accepts (body, options = {}) and calls count on the Elasticsearch::Transport::Client. Automatically adds the index and type option to your queries.

Returns Hash response from Elasticsearch::Transport::Client.

type.count({ query: { match: { title: 'Tron' } } })
# => {"count"=>1, "_shards"=>{"total"=>5, "successful"=>5, "failed"=>0}}
exists?

Accepts (options = {}) and calls exists? on the Elasticsearch::Transport::Client. Automatically adds the index and type option to your queries.

Returns true or false.

type.exists?(id: 'tron')
# => true
create

Accepts (options = {}) and calls create on the Elasticsearch::Transport::Client. Automatically adds the index and type option to your queries.

Throws error if document already exists.

type.create(id: 'tron', body: { })
update

Accepts (options = {}) and calls update on the Elasticsearch::Transport::Client. Automatically adds the index and type option to your queries.

type.update(id: 'tron', body: { })
delete

Accepts (options = {}) and calls delete on the Elasticsearch::Transport::Client. Automatically adds the index and type option to your queries.

Throws error if document doesn't exist.

type.delete(id: 'tron')
get

Accepts (options = {}) and calls get on the Elasticsearch::Transport::Client. Automatically adds the index and type option to your queries.

Returns Elasticsearch::Resources::Document.

type.get(id: 'tron')
# => #<Elasticsearch::Resources::Document>

Document

An Elasticsearch::Resources::Document represents an ElasticSearch document within an index. Requires an id and Type (see "Type" above.)

# Create a document
document = Elasticsearch::Resources::Document.new(
  type: type, # (Required)
  id: 'tron', # (Required)
  attributes: { title: 'Tron' } # (Optional)
)
id

Returns a String of the Document ID.

document.id
# => 'tron'
attributes

Returns a Hash of the Document body.

document.attributes
# => { 'title' => 'Tron' }
client

Returns the underlying Elasticsearch::Transport::Client.

document.client
exists?

Accepts (options = {}) and calls exists? on the Elasticsearch::Transport::Client. Automatically adds the index, type and id option to your queries.

Returns true or false.

document.exists?
# => true
create

Accepts (options = {}) and calls create on the Elasticsearch::Transport::Client. Automatically adds the index, type, id, and body option to your queries.

Throws error if document already exists.

document.create
update

Accepts (options = {}) and calls update on the Elasticsearch::Transport::Client. Automatically adds the index, type, id, and body option to your queries.

document.update
delete

Accepts (options = {}) and calls delete on the Elasticsearch::Transport::Client. Automatically adds the index, type and id option to your queries.

Throws error if document doesn't exist.

document.delete
get

Accepts (options = {}) and calls get on the Elasticsearch::Transport::Client. Automatically adds the index, type and id option to your queries.

Returns Elasticsearch::Resources::Document.

document.get
# => #<Elasticsearch::Resources::Document>

Defining well known resources

Cluster

class DavesAwesomeMovies < Elasticsearch::Resources::Cluster
  # Set any default configuration settings here.
  define_configuration defaults: -> { |cluster|
    cluster.host = 'davesawesomemovies.com:9200'
  }

  # Provide a hash of keys to Index class names (either constants or strings)
  define_indexes film: 'Film'
end

cluster = DavesAwesomeMovies.new
cluster.indexes[:film] # => #<Film>

Index

class Film < Elasticsearch::Resources::Index
  # Set any default configuration settings here.
  # Probably should set a name.
  define_configuration defaults: -> { |index|
    index.name = 'film'
  }

  # Provide a hash of keys to Type class names (either constants or strings)
  define_type movie: 'Movie'
end

film = Film.new
film.types[:movies] # => #<Movies>

Type

class Movies < Elasticsearch::Resources::Type
  # Set any default configuration settings here.
  # Probably should set a name.
  define_configuration defaults: -> { |type|
    type.name = 'movie'
  }

  # Provide a Document class name (either constants or strings)
  # If not called, type will return Elasticsearch::Resources::Document objects instead.
  define_document 'Movie'
end

movies = Movies.new
movies.get(id: 'tron') # => #<Movie>

Document

class Movie < Elasticsearch::Resources::Document
  # Provide a list of well known attributes
  define_attributes :title, :year
end

movie = Movie.new(id: 'tron', type: movies, attributes: { title: 'Tron', year: 1982 })
movie.title # => 'Tron'
movie.year # => 1982

Development

Install dependencies using bundle install. Run tests using bundle exec rspec

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/delner/elasticsearch-resources.

License

The gem is available as open source under the terms of the Apache 2.0 License.