-
Notifications
You must be signed in to change notification settings - Fork 256
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
38 changed files
with
649 additions
and
137 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# frozen_string_literal: true | ||
|
||
module Blacklight | ||
module Elasticsearch | ||
autoload :Repository, "blacklight/elasticsearch/repository" | ||
autoload :SearchBuilderBehavior, "blacklight/elasticsearch/search_builder_behavior" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
# frozen_string_literal: true | ||
|
||
module Blacklight::Elasticsearch | ||
class Repository < Blacklight::AbstractRepository | ||
class SingleDocumentResponse | ||
def initialize doc | ||
@doc = doc | ||
end | ||
|
||
def documents | ||
[@doc] | ||
end | ||
end | ||
|
||
class FacetResponse | ||
attr_reader :name, :aggregation | ||
|
||
def initialize name, aggregation | ||
@name = name | ||
@aggregation = aggregation | ||
end | ||
|
||
def items | ||
aggregation.buckets.map do |b| | ||
OpenStruct.new(name: name, value: b['key'], hits: b['doc_count']) | ||
end | ||
end | ||
|
||
def sort; end | ||
|
||
def offset; end | ||
|
||
def limit; end | ||
end | ||
|
||
class NullSpelling | ||
def words | ||
[] | ||
end | ||
end | ||
|
||
class SearchResponse | ||
attr_reader :response, :params | ||
|
||
include Kaminari::PageScopeMethods | ||
include Kaminari::ConfigurationMethods::ClassMethods | ||
|
||
def initialize response, params | ||
@response = response | ||
@params = params | ||
end | ||
|
||
def inspect | ||
"#<#{self.class.name} results=#{response.results}>" | ||
end | ||
|
||
def grouped? | ||
false | ||
end | ||
|
||
delegate :results, :total, to: :response | ||
|
||
alias documents results | ||
|
||
delegate :empty?, to: :results | ||
|
||
def facet_by_field_name field_name | ||
agg = response.response.aggregations[field_name] | ||
return unless agg | ||
FacetResponse.new(field_name, agg) | ||
end | ||
|
||
def docs | ||
response.results | ||
end | ||
|
||
# TODO: not yet implemented | ||
def aggregations | ||
{} | ||
end | ||
|
||
def facet_pivot *_args | ||
{} | ||
end | ||
|
||
def facet_queries *_args | ||
[] | ||
end | ||
|
||
alias total_count total | ||
|
||
def start | ||
params['from'] || 0 | ||
end | ||
alias offset_value start | ||
|
||
def limit_value | ||
params['size'] || response.size | ||
end | ||
alias rows limit_value | ||
|
||
def sort | ||
nil | ||
end | ||
|
||
def spelling | ||
NullSpelling.new | ||
end | ||
end | ||
|
||
## | ||
# Find a single document result (by id) using the document configuration | ||
# @param [String] document's unique key value | ||
def find id, _params = {} | ||
SingleDocumentResponse.new(connection.find(id)) | ||
rescue Elasticsearch::Persistence::Repository::DocumentNotFound | ||
raise Blacklight::Exceptions::RecordNotFound | ||
end | ||
|
||
## | ||
# Execute a search query | ||
# @param [Hash] elastic search query parameters | ||
def search params = {} | ||
Rails.logger.info "ES parameters: #{params.to_h}" | ||
SearchResponse.new(connection.search(params.to_h), params) | ||
end | ||
|
||
def suggestions(request_params) | ||
key = 'resp' | ||
Blacklight::Suggest::Response.new({}, request_params, key) | ||
end | ||
|
||
private | ||
|
||
def build_connection | ||
c = Elasticsearch::Client.new connection_config.except(:adapter, :index) | ||
idx = connection_config[:index] | ||
Elasticsearch::Persistence::Repository.new do | ||
# Configure the Elasticsearch client | ||
client c | ||
|
||
# Set a custom index name | ||
index idx | ||
|
||
type :document | ||
|
||
klass ElasticsearchDocument | ||
|
||
settings number_of_shards: 1 do | ||
mapping do | ||
indexes :text, analyzer: 'snowball' | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# frozen_string_literal: true | ||
|
||
module Blacklight::Elasticsearch | ||
module SearchBuilderBehavior | ||
extend ActiveSupport::Concern | ||
included do | ||
self.default_processor_chain = [:default_parameters, :build_query, :add_filters, :add_aggregations, :add_pagination, :add_sort] | ||
end | ||
#### | ||
# Start with general defaults from BL config. Need to use custom | ||
# merge to dup values, to avoid later mutating the original by mistake. | ||
def default_parameters(es_parameters) | ||
return unless blacklight_config.default_elasticsearch_params | ||
|
||
blacklight_config.default_elasticsearch_params.each do |key, value| | ||
es_parameters[key] = if value.respond_to? :deep_dup | ||
value.deep_dup | ||
elsif value.respond_to?(:dup) && value.duplicable? | ||
value.dup | ||
else | ||
value | ||
end | ||
end | ||
end | ||
|
||
def build_query(es_parameters) | ||
return unless blacklight_params[:q] | ||
es_parameters[:query] ||= {} | ||
|
||
if blacklight_params[:q].is_a? Hash | ||
es_parameters[:query][:match] ||= {} | ||
|
||
blacklight_params[:q].each do |k, v| | ||
es_parameters[:query][:match][k] = v | ||
end | ||
return | ||
end | ||
|
||
if search_field && search_field.template | ||
es_parameters[:query][:template] = search_field.template.dup | ||
es_parameters[:query][:template][:params] ||= {} | ||
es_parameters[:query][:template][:params][:q] = blacklight_params[:q] | ||
else | ||
es_parameters[:query][:match] ||= {} | ||
es_parameters[:query][:match][:_all] = blacklight_params[:q] | ||
end | ||
end | ||
|
||
def add_filters(es_parameters) | ||
return unless blacklight_params[:f] | ||
es_parameters[:query] ||= {} | ||
es_parameters[:query][:filtered] ||= {} | ||
es_parameters[:query][:filtered][:filter] ||= {} | ||
es_parameters[:query][:filtered][:filter][:term] ||= {} | ||
|
||
blacklight_params[:f].each_pair do |facet_field, value_list| | ||
facet_config = blacklight_config.facet_fields[facet_field] | ||
|
||
field = facet_config.field if facet_config | ||
field ||= facet_field | ||
|
||
es_parameters[:query][:filtered][:filter][:term][field] ||= value_list | ||
end | ||
end | ||
|
||
def add_aggregations(es_parameters) | ||
es_parameters[:aggregations] ||= {} | ||
|
||
results = blacklight_config.facet_fields.select do |_field_name, facet| | ||
facet.include_in_request || (facet.include_in_request.nil? && blacklight_config.add_facet_fields_to_solr_request) | ||
end | ||
|
||
results.each do |_key, facet_config| | ||
es_parameters[:aggregations][facet_config.field] = { terms: { field: facet_config.field } } | ||
end | ||
end | ||
|
||
def add_pagination(es_parameters) | ||
es_parameters[:from] = start | ||
es_parameters[:size] = rows | ||
end | ||
|
||
def add_sort(es_parameters) | ||
es_parameters[:sort] = sort if sort.present? | ||
end | ||
|
||
def query(*args) | ||
super.except(:fl, :facet) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
require 'rails/generators' | ||
|
||
module Blacklight | ||
class ElasticsearchGenerator < Rails::Generators::Base | ||
source_root ::File.expand_path('../templates', __FILE__) | ||
|
||
desc <<-EOF | ||
This generator makes the following changes to your application: | ||
1. Adds elasticsearch gems to your Gemfile | ||
EOF | ||
|
||
def add_gems | ||
gem 'elasticsearch-model' | ||
gem 'elasticsearch-rails' | ||
gem 'elasticsearch-persistence' | ||
end | ||
end | ||
end |
Oops, something went wrong.