Commit f0f6b810b6b4249eaa648dbf3294d2c36d12b8f4

Authored by Braulio Bhavamitra
Committed by Daniela Feitosa
1 parent 4197c870

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 :)
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?