diff --git a/app/helpers/blacklight/blacklight_helper_behavior.rb b/app/helpers/blacklight/blacklight_helper_behavior.rb index 4e680e843f..65d8359c1b 100644 --- a/app/helpers/blacklight/blacklight_helper_behavior.rb +++ b/app/helpers/blacklight/blacklight_helper_behavior.rb @@ -131,7 +131,7 @@ def document_has_value? document, field_config # @param [Blacklight::SolrResponse] response # @return [Boolean] def should_show_spellcheck_suggestions? response - response.total <= spell_check_max and response.spelling.words.size > 0 + response.total <= spell_check_max and response.spelling and response.spelling.words.size > 0 end ## diff --git a/blacklight.gemspec b/blacklight.gemspec index 526a5749cb..b70f1f8a19 100644 --- a/blacklight.gemspec +++ b/blacklight.gemspec @@ -23,6 +23,9 @@ Gem::Specification.new do |s| s.add_dependency "rsolr", "~> 1.0.11" # Library for interacting with rSolr. s.add_dependency "bootstrap-sass", "~> 3.2" s.add_dependency "deprecation" + s.add_dependency "elasticsearch-model" + s.add_dependency "elasticsearch-rails" + s.add_dependency "elasticsearch-persistence" s.add_development_dependency "jettywrapper", ">= 1.7.0" s.add_development_dependency "blacklight-marc", "~> 5.0" diff --git a/lib/blacklight.rb b/lib/blacklight.rb index 9e74840841..0b2aa401e0 100644 --- a/lib/blacklight.rb +++ b/lib/blacklight.rb @@ -2,7 +2,7 @@ require 'kaminari' require 'deprecation' require 'blacklight/utils' - +require 'elasticsearch' module Blacklight autoload :Configurable, 'blacklight/configurable' autoload :Configuration, 'blacklight/configuration' @@ -34,6 +34,8 @@ module Blacklight autoload :SolrResponse, 'blacklight/solr_response' autoload :Facet, 'blacklight/facet' + + autoload :Elasticsearch, 'blacklight/elasticsearch' extend SearchFields extend Deprecation @@ -69,7 +71,7 @@ def self.solr end def self.default_index - @default_index ||= Blacklight::SolrRepository.new(Blacklight::Configuration.new) + @default_index ||= repository_class.new(default_configuration) end def self.solr_config @@ -77,6 +79,21 @@ def self.solr_config connection_config end + def self.repository_class + case connection_config[:adapter] + when "elasticsearch" + Blacklight::Elasticsearch::Repository + when "solr" + Blacklight::SolrRepository + else + raise "No connection adapter found" + end + end + + def self.default_configuration + @default_configuration ||= Blacklight::Configuration.new + end + def self.connection_config @connection_config ||= begin raise "The #{::Rails.env} environment settings were not found in the blacklight.yml config" unless blacklight_yml[::Rails.env] diff --git a/lib/blacklight/catalog/search_context.rb b/lib/blacklight/catalog/search_context.rb index b3d518370d..d5cee2f0bd 100644 --- a/lib/blacklight/catalog/search_context.rb +++ b/lib/blacklight/catalog/search_context.rb @@ -103,6 +103,8 @@ def setup_next_and_previous_documents end rescue Blacklight::Exceptions::InvalidRequest => e logger.warn "Unable to setup next and previous documents: #{e}" + rescue Elasticsearch::Transport::Transport::Errors::BadRequest => e + logger.warn "Unable to setup next and previous documents: #{e}" end end diff --git a/lib/blacklight/routes.rb b/lib/blacklight/routes.rb index c2414b52fb..a2f1b35930 100644 --- a/lib/blacklight/routes.rb +++ b/lib/blacklight/routes.rb @@ -122,7 +122,7 @@ def solr_document(primary_resource) args = {only: [:show]} args[:constraints] = options[:constraints] if options[:constraints] - resources :solr_document, args.merge(path: primary_resource, controller: primary_resource) do + resources :elasticsearch_document, args.merge(path: primary_resource, controller: primary_resource) do member do post "track" end diff --git a/lib/generators/blacklight/templates/catalog_controller.rb b/lib/generators/blacklight/templates/catalog_controller.rb index c7486e5722..8d72f2caa1 100644 --- a/lib/generators/blacklight/templates/catalog_controller.rb +++ b/lib/generators/blacklight/templates/catalog_controller.rb @@ -1,9 +1,17 @@ # -*- encoding : utf-8 -*- -class <%= controller_name.classify %>Controller < ApplicationController +class CatalogController < ApplicationController + include Blacklight::Marc::Catalog include Blacklight::Catalog + self.search_params_logic = true + configure_blacklight do |config| + + config.repository_class = Blacklight::Elasticsearch::Repository + config.document_model = ElasticsearchDocument + config.search_builder_class = Blacklight::Elasticsearch::SearchBuilder + ## Default parameters to send to solr for all search-like requests. See also SearchBuilder#processed_parameters config.default_solr_params = { :qt => 'search', @@ -54,13 +62,13 @@ class <%= controller_name.classify %>Controller < ApplicationController # # :show may be set to false if you don't want the facet to be drawn in the # facet bar - config.add_facet_field 'format', :label => 'Format' + config.add_facet_field 'format', :label => 'Format', field: 'format.raw' config.add_facet_field 'pub_date', :label => 'Publication Year', :single => true - config.add_facet_field 'subject_topic_facet', :label => 'Topic', :limit => 20 - config.add_facet_field 'language_facet', :label => 'Language', :limit => true - config.add_facet_field 'lc_1letter_facet', :label => 'Call Number' - config.add_facet_field 'subject_geo_facet', :label => 'Region' - config.add_facet_field 'subject_era_facet', :label => 'Era' + config.add_facet_field 'subject_topic_facet', :label => 'Topic', :limit => 20, field: 'subject_topic_facet.raw' + config.add_facet_field 'language_facet', :label => 'Language', :limit => true , field: 'language_facet.raw' + config.add_facet_field 'lc_1letter_facet', :label => 'Call Number' , field: 'lc_1letter_facet.raw' + config.add_facet_field 'subject_geo_facet', :label => 'Region' , field: 'subject_geo_facet.raw' + config.add_facet_field 'subject_era_facet', :label => 'Era' , field: 'subject_era_facet.raw' config.add_facet_field 'example_pivot_field', :label => 'Pivot Field', :pivot => ['format', 'language_facet'] @@ -124,54 +132,31 @@ class <%= controller_name.classify %>Controller < ApplicationController # since we aren't specifying it otherwise. config.add_search_field 'all_fields', :label => 'All Fields' - # Now we see how to over-ride Solr request handler defaults, in this # case for a BL "search field", which is really a dismax aggregate # of Solr search fields. - config.add_search_field('title') do |field| - # solr_parameters hash are sent to Solr as ordinary url query params. - field.solr_parameters = { :'spellcheck.dictionary' => 'title' } - - # :solr_local_parameters will be sent using Solr LocalParams - # syntax, as eg {! qf=$title_qf }. This is neccesary to use - # Solr parameter de-referencing like $title_qf. - # See: http://wiki.apache.org/solr/LocalParams - field.solr_local_parameters = { - :qf => '$title_qf', - :pf => '$title_pf' - } - end + config.add_search_field('title', template: { + query: ({ match: { title_t: "{{q}}" } }) + }) - config.add_search_field('author') do |field| - field.solr_parameters = { :'spellcheck.dictionary' => 'author' } - field.solr_local_parameters = { - :qf => '$author_qf', - :pf => '$author_pf' - } - end + config.add_search_field('author', template: { + query: ({ match: { author_t: "{{q}}" } }) + }) - # Specifying a :qt only to show it's possible, and so our internal automated - # tests can test it. In this case it's the same as - # config[:default_solr_parameters][:qt], so isn't actually neccesary. - config.add_search_field('subject') do |field| - field.solr_parameters = { :'spellcheck.dictionary' => 'subject' } - field.qt = 'search' - field.solr_local_parameters = { - :qf => '$subject_qf', - :pf => '$subject_pf' - } - end + config.add_search_field('subject', template: { + query: ({ match: { subject_t: "{{q}}" } }) + }) # "sort results by" select (pulldown) # label in pulldown is followed by the name of the SOLR field to sort by and # whether the sort is ascending or descending (it must be asc or desc # except in the relevancy case). - config.add_sort_field 'score desc, pub_date_sort desc, title_sort asc', :label => 'relevance' - config.add_sort_field 'pub_date_sort desc, title_sort asc', :label => 'year' - config.add_sort_field 'author_sort asc, title_sort asc', :label => 'author' - config.add_sort_field 'title_sort asc, pub_date_sort desc', :label => 'title' + config.add_sort_field 'relevance', sort: [{"_score" => { order: "desc" }}, {"pub_date_sort.raw" => { order: "desc"}}, { "title_sort.raw" => { order: "asc"}}], :label => 'relevance' + config.add_sort_field 'year', sort: [{"pub_date_sort.raw" => { order: "desc"}}, { "title_sort.raw" => { order: "asc"}}], :label => 'year' + config.add_sort_field 'author', sort: [{"author_sort.raw" => { order: "asc"}}, { "title_sort.raw" => { order: "asc"}}], :label => 'author' + config.add_sort_field 'title', sort: [{ "title_sort.raw" => { order: "asc"}}, {"pub_date_sort.raw" => { order: "desc"}}], :label => 'title' # If there are more than this many search results, no spelling ("did you # mean") suggestion is offered. diff --git a/lib/railties/blacklight.rake b/lib/railties/blacklight.rake index 028eb7ad71..aca01289eb 100644 --- a/lib/railties/blacklight.rake +++ b/lib/railties/blacklight.rake @@ -12,11 +12,23 @@ namespace :blacklight do namespace :index do desc "Put sample data into solr" - task :seed do - docs = YAML::load(File.open(File.join(Blacklight.root, 'solr', 'sample_solr_documents.yml'))) - conn = Blacklight.default_index.connection - conn.add docs - conn.commit + task :seed, [:file] => [:environment] do |t, args| + args.with_defaults(file: File.join(Blacklight.root, 'solr', 'sample_solr_documents.yml')) + + docs = YAML::load(File.open(args[:file])) + + case Blacklight.default_index + when Blacklight::Elasticsearch::Repository + ElasticsearchDocument.create_index! force: true + docs.each do |h| + ElasticsearchDocument.new(h.except('timestamp')).save + end + when Blacklight::SolrRepository + conn = Blacklight.default_index.connection + + conn.add docs + conn.commit + end end end