Commit f0f6b810b6b4249eaa648dbf3294d2c36d12b8f4
Committed by
Daniela Feitosa
1 parent
4197c870
Exists in
master
and in
29 other branches
Support multitenancy on searches
Prefix Solr unique id with schema_path to avoid colision. Fix rake multitenancy:reindex to reindex all environments now that we can :)
Showing
4 changed files
with
30 additions
and
39 deletions
Show diff stats
config/solr.yml.dist
| @@ -3,25 +3,8 @@ | @@ -3,25 +3,8 @@ | ||
| 3 | # If you change the host or port number here, make sure you update | 3 | # If you change the host or port number here, make sure you update |
| 4 | # them in your Solr config file | 4 | # them in your Solr config file |
| 5 | 5 | ||
| 6 | -# This file must follow a structure in order to achieve multitenancy | ||
| 7 | -# support. In this example, we will configure solr to support 3 | ||
| 8 | -# different schemas: env1, env2 and env3. | ||
| 9 | -# | ||
| 10 | -# Each "hosted" environment must have an entry like this: | ||
| 11 | -# | ||
| 12 | -# production: &PRODUCTION | ||
| 13 | -# url: http://127.0.0.1:8983/solr | ||
| 14 | -# jvm_options: -server -Xmx192M -Xms64M | ||
| 15 | -# timeout: 0 | ||
| 16 | -# | ||
| 17 | -# env1_production: | ||
| 18 | -# <<: *PRODUCTION | ||
| 19 | -# | ||
| 20 | -# env2_production: | ||
| 21 | -# <<: *PRODUCTION | ||
| 22 | -# | ||
| 23 | -# env3_production: | ||
| 24 | -# <<: *PRODUCTION | 6 | +# No change is need to support multitenancy. Only one solr environment is need. |
| 7 | +# Just remember to use 'rake multitenancy:reindex' for reindexation. | ||
| 25 | 8 | ||
| 26 | production: | 9 | production: |
| 27 | url: http://127.0.0.1:8983/solr | 10 | url: http://127.0.0.1:8983/solr |
lib/acts_as_searchable.rb
| @@ -6,12 +6,13 @@ module ActsAsSearchable | @@ -6,12 +6,13 @@ module ActsAsSearchable | ||
| 6 | def acts_as_searchable(options = {}) | 6 | def acts_as_searchable(options = {}) |
| 7 | return if !ACTS_AS_SEARCHABLE_ENABLED | 7 | return if !ACTS_AS_SEARCHABLE_ENABLED |
| 8 | 8 | ||
| 9 | - if (!options[:fields]) | ||
| 10 | - options[:additional_fields] ||= [] | ||
| 11 | - options[:additional_fields] |= [{:schema_name => :string}] | ||
| 12 | - else | 9 | + if options[:fields] |
| 13 | options[:fields] << {:schema_name => :string} | 10 | options[:fields] << {:schema_name => :string} |
| 11 | + else | ||
| 12 | + options[:additional_fields] ||= [] | ||
| 13 | + options[:additional_fields] << {:schema_name => :string} | ||
| 14 | end | 14 | end |
| 15 | + | ||
| 15 | acts_as_solr options | 16 | acts_as_solr options |
| 16 | extend FindByContents | 17 | extend FindByContents |
| 17 | send :include, InstanceMethods | 18 | send :include, InstanceMethods |
| @@ -19,7 +20,15 @@ module ActsAsSearchable | @@ -19,7 +20,15 @@ module ActsAsSearchable | ||
| 19 | 20 | ||
| 20 | module InstanceMethods | 21 | module InstanceMethods |
| 21 | def schema_name | 22 | def schema_name |
| 22 | - (Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?) ? ActiveRecord::Base.connection.schema_search_path : '' | 23 | + self.class.schema_name |
| 24 | + end | ||
| 25 | + | ||
| 26 | + # replace solr_id from vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/instance_methods.rb | ||
| 27 | + # to include schema_name | ||
| 28 | + def solr_id | ||
| 29 | + id = "#{self.class.name}:#{record_id(self)}" | ||
| 30 | + id.insert(0, "#{schema_name}:") unless schema_name.blank? | ||
| 31 | + id | ||
| 23 | end | 32 | end |
| 24 | end | 33 | end |
| 25 | 34 | ||
| @@ -36,7 +45,7 @@ module ActsAsSearchable | @@ -36,7 +45,7 @@ module ActsAsSearchable | ||
| 36 | options[:per_page] = pg_options[:per_page].to_i | 45 | options[:per_page] = pg_options[:per_page].to_i |
| 37 | options[:scores] ||= true | 46 | options[:scores] ||= true |
| 38 | options[:filter_queries] ||= [] | 47 | options[:filter_queries] ||= [] |
| 39 | - options[:filter_queries] << "schema_name:\"#{schema_name}\"" unless schema_name.empty? | 48 | + options[:filter_queries] << "schema_name:\"#{schema_name}\"" unless schema_name.blank? |
| 40 | all_facets_enabled = options.delete(:all_facets) | 49 | all_facets_enabled = options.delete(:all_facets) |
| 41 | options[:per_page] = options.delete(:extra_limit) if options[:extra_limit] | 50 | options[:per_page] = options.delete(:extra_limit) if options[:extra_limit] |
| 42 | results = [] | 51 | results = [] |
lib/tasks/multitenancy.rake
| @@ -15,18 +15,17 @@ namespace :multitenancy do | @@ -15,18 +15,17 @@ namespace :multitenancy do | ||
| 15 | end | 15 | end |
| 16 | 16 | ||
| 17 | task :reindex => :environment do | 17 | task :reindex => :environment do |
| 18 | - envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_#{RAILS_ENV}$/) } | ||
| 19 | - models = [ Profile, Article, Product ] | ||
| 20 | - envs.each do |e| | ||
| 21 | - puts "Rebuilding Index for #{e}" if Rake.application.options.trace | 18 | + # enable output from rebuild_index |
| 19 | + logger = ActiveRecord::Base.logger = Logger.new(STDOUT) | ||
| 20 | + logger.level = ActiveSupport::BufferedLogger::INFO | ||
| 21 | + | ||
| 22 | + db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_#{RAILS_ENV}$/) } | ||
| 23 | + db_envs.each do |e| | ||
| 24 | + puts "REBUILDING INDEX FOR ENVIRONMENT #{e}" | ||
| 22 | ActiveRecord::Base.connection.schema_search_path = ActiveRecord::Base.configurations[e]['schema_search_path'] | 25 | ActiveRecord::Base.connection.schema_search_path = ActiveRecord::Base.configurations[e]['schema_search_path'] |
| 23 | - models.each do |m| | ||
| 24 | - if e == envs[0] | ||
| 25 | - m.rebuild_index | ||
| 26 | - puts "Rebuilt index for #{m}" if Rake.application.options.trace | ||
| 27 | - end | ||
| 28 | - m.paginated_each(:per_page => 50) { |i| i.solr_save } | ||
| 29 | - puts "Reindexed all instances of #{m}" if Rake.application.options.trace | 26 | + $solr_indexed_models.each do |m| |
| 27 | + puts "Rebuilding index for model #{m}" | ||
| 28 | + m.rebuild_index | ||
| 30 | end | 29 | end |
| 31 | end | 30 | end |
| 32 | end | 31 | end |
vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/parser_methods.rb
| @@ -30,7 +30,7 @@ module ActsAsSolr #:nodoc: | @@ -30,7 +30,7 @@ module ActsAsSolr #:nodoc: | ||
| 30 | query = replace_types([*query], ':').first | 30 | query = replace_types([*query], ':').first |
| 31 | end | 31 | end |
| 32 | 32 | ||
| 33 | - query_options[:filter_queries] += replace_types([*options[:filter_queries]], '') if options[:filter_queries] | 33 | + query_options[:filter_queries] += replace_types([*options[:filter_queries]], ':') if options[:filter_queries] |
| 34 | 34 | ||
| 35 | options[:alternate_query] ||= '' | 35 | options[:alternate_query] ||= '' |
| 36 | options[:alternate_query].strip! | 36 | options[:alternate_query].strip! |
| @@ -125,7 +125,7 @@ module ActsAsSolr #:nodoc: | @@ -125,7 +125,7 @@ module ActsAsSolr #:nodoc: | ||
| 125 | def solr_type_condition(options = {}) | 125 | def solr_type_condition(options = {}) |
| 126 | classes = [self] + (self.subclasses || []) + (options[:models] || []) | 126 | classes = [self] + (self.subclasses || []) + (options[:models] || []) |
| 127 | classes.map do |klass| | 127 | classes.map do |klass| |
| 128 | - next if klass.name.empty? | 128 | + next if klass.name.empty? |
| 129 | "#{solr_configuration[:type_field]}:\"#{klass.name}\"" | 129 | "#{solr_configuration[:type_field]}:\"#{klass.name}\"" |
| 130 | end.compact.join(' OR ') | 130 | end.compact.join(' OR ') |
| 131 | end | 131 | end |
| @@ -248,7 +248,7 @@ module ActsAsSolr #:nodoc: | @@ -248,7 +248,7 @@ module ActsAsSolr #:nodoc: | ||
| 248 | bad_options = options.map {|x| x.to_sym} - valid_other_options | 248 | bad_options = options.map {|x| x.to_sym} - valid_other_options |
| 249 | raise "Invalid option#{'s' if bad_options.size > 1} for faceted date's other param: #{bad_options.join(', ')}. May only be one of :after, :all, :before, :between, :none" if bad_options.size > 0 | 249 | raise "Invalid option#{'s' if bad_options.size > 1} for faceted date's other param: #{bad_options.join(', ')}. May only be one of :after, :all, :before, :between, :none" if bad_options.size > 0 |
| 250 | end | 250 | end |
| 251 | - | 251 | + |
| 252 | def sanitize_query(query) | 252 | def sanitize_query(query) |
| 253 | fields = self.configuration[:solr_fields].keys | 253 | fields = self.configuration[:solr_fields].keys |
| 254 | fields += DynamicAttribute.all(:select => 'name', :group => 'name').map(&:name) if DynamicAttribute.table_exists? | 254 | fields += DynamicAttribute.all(:select => 'name', :group => 'name').map(&:name) if DynamicAttribute.table_exists? |