
Security News
Follow-up and Clarification on Recent Malicious Ruby Gems Campaign
A clarification on our recent research investigating 60 malicious Ruby gems.
ElasticRecord is an Elasticsearch 6.x and 7.x ORM.
Include ElasticRecord into your model:
class Product < ActiveRecord::Base
include ElasticRecord::Model
end
There are two ways to set up which server to connect to:
# config/initializers/elastic_search.rb
ElasticRecord.configure do |config|
config.servers = "es1.example.com:9200"
end
# config/elasticsearch.yml:
development:
servers: es1.example.com:9200
timeout: 10
retries: 2
ElasticRecord adds the method 'elastic_search' to your models. It works similar to active_record scoping:
search = Product.elastic_search
If a simple hash is passed into filter, a term or terms query is created:
search.filter(color: 'red') # Creates a 'term' filter
search.filter(color: %w(red blue)) # Creates a 'terms' filter
search.filter(color: nil) # Creates a 'must not exist' filter
If a hash containing hashes is passed into filter, it is used directly as a filter DSL expression:
search.filter(prefix: { name: "Sca" }) # Creates a prefix filter
An Arelastic object can also be passed in, working similarily to Arel:
# Name starts with 'Sca'
search.filter(Product.arelastic[:name].prefix("Sca"))
# Name does not start with 'Sca'
search.filter(Product.arelastic[:name].prefix("Sca").negate)
# Size is greater than 5
search.filter(Product.arelastic[:size].gt(5))
Helpful Arel builders can be found at https://github.com/matthuhiggins/arelastic/blob/master/lib/arelastic/builders/filter.rb.
To create a query string, pass a string to search.query:
search.query("red AND fun*") # Creates {query_string: {"red AND fun*"}}
Complex queries are done using either a hash or an arelastic object:
search.query(match: {description: "amazing"})
search.order(:price) # sort by price
search.order(:color, :price) # sort by color, then price
search.order(price: :desc) # sort by price in descending order
To change the 'size' and 'from' values of a query, use offset and limit:
search.limit(40).offset(80) # Creates a query with {size: 40, from: 80}
Aggregations are added with the aggregate method:
search.aggregate('popular_colors' => {'terms' => {'field' => 'color'}})
Results are retrieved at query time within aggregations
:
search = search.aggregate('popular_colors' => {'terms' => {'field' => 'color'}})
search.aggregations['popular_colors'].buckets
A search object behaves similar to an active_record scope, implementing a few methods of its own and delegating the rest to Array, and your class.
search.count # Return the number of search results
search.first # Limit results to 1 and return the first result or nil
search.find(id) # Add an ids filter to the existing query
search.as_elastic # Return the json hash that will be sent to elastic search.
The search object behaves like an array when necessary:
search.each do |product|
...
end
Class methods can be executed within scopes:
class Product
def self.increase_prices
all.each do { |product| product.increment(:price, 10) }
end
end
# Increase the price of all red products by $10.
Product.filter(color: 'red').increase_prices
ElasticRecord supports representing query documents as a model. Queries are registered and unregistered as query models are created and destroyed.
First, include ElasticRecord::PercolatorModel
into your model. Specify the target model to percolate and how the model should be indexed as an ElasticSearch query.
class ProductQuery
include ElasticRecord::PercolatorModel
self.percolates_model = Product
def as_search_document
Product.filter(status: status).as_elastic
end
end
Use the percolate
method to find records with queries that match.
product = Product.new(price: 5.99)
matching_product_queries = ProductQuery.percolate(product)
To avoid elasticsearch dynamically mapping fields, you can directly configure elastic_index.mapping
and elastic_index.settings
:
class Product
include ElasticRecord::Model
elastic_index.mapping = {
properties: {
name: {type: "text"},
status: {type: "keyword"}
}
}
end
Mapping types will be removed in ElasticSearch 7.x. To rename the default mapping type (_doc
), use elastic_index.mapping_type
:
class Product
include ElasticRecord::Model
elastic_index.mapping_type = 'product'
end
When one model inherits from another, ElasticRecord makes some assumptions about how the child index should be configured. By default:
alias_name
- Same as parentmapping
- Same as parentmapping_type
- Same as parentsettings
- Same as parentThese can all be overridden. For instance, it might be desirable for the child documents to be in a separate index.
To fetch documents without an additional request to a backing ActiveRecord database you can load the documents from _source
.
Product.elastic_index.loading_from_source do
Product.elastic_search.filter(name: "Pizza")
end
Call load_from_source!
to configure an index without ActiveRecord. Finder methods will be
delegated to the ElasticRecord module.
class Product
include ActiveModel::Model
include ElasticRecord::Record
elastic_index.load_from_source!
end
If you need to manage multiple indexes via the rake tasks, you will need to declare them explicitly:
ElasticRecord.configure do |config|
config.model_names = %w(Product Order Location)
end
Create the index:
rake index:create CLASS=Product
Core and Index APIs can be accessed with Product.elastic_index. Some examples include:
Product.elastic_index.create_and_deploy # Create a new index
Product.elastic_index.reset # Delete related indexes and deploy a new one
Product.elastic_index.refresh # Call the refresh API
Product.elastic_index.get_mapping # Get the index mapping defined by elastic search
FAQs
Unknown package
We found that elastic_record demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
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.
Security News
A clarification on our recent research investigating 60 malicious Ruby gems.
Security News
ESLint now supports parallel linting with a new --concurrency flag, delivering major speed gains and closing a 10-year-old feature request.
Research
/Security News
A malicious Go module posing as an SSH brute forcer exfiltrates stolen credentials to a Telegram bot controlled by a Russian-speaking threat actor.