multi-solr 01.01.05

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/Rakefile +1 -0
  5. data/lib/multi_solr/base_searcher.rb +393 -0
  6. data/lib/multi_solr/filter_value_composite.rb +33 -0
  7. data/lib/multi_solr/rails_form_render_helper.rb +84 -0
  8. data/lib/multi_solr/search_request.rb +209 -0
  9. data/lib/multi_solr/search_result.rb +127 -0
  10. data/lib/multi_solr/single_core_handler.rb +341 -0
  11. data/lib/multi_solr/solr_filter_collection.rb +97 -0
  12. data/lib/multi_solr/solr_filter_date.rb +46 -0
  13. data/lib/multi_solr/solr_filter_date_range.rb +62 -0
  14. data/lib/multi_solr/solr_filter_free_query.rb +11 -0
  15. data/lib/multi_solr/solr_filter_simple.rb +96 -0
  16. data/lib/multi_solr/timeline_core_handler.rb +131 -0
  17. data/lib/multi_solr/version.rb +3 -0
  18. data/lib/multi_solr.rb +43 -0
  19. data/multi-solr.gemspec +28 -0
  20. data/spec/fixtures/solr-testdata.yml +13 -0
  21. data/spec/multi_solr/base_searcher_spec.rb +212 -0
  22. data/spec/multi_solr/search_request_spec.rb +45 -0
  23. data/spec/multi_solr/search_result_spec.rb +113 -0
  24. data/spec/multi_solr/single_core_handler_spec.rb +169 -0
  25. data/spec/multi_solr/timeline_core_handler_spec.rb +107 -0
  26. data/spec/solr_test_helper.rb +15 -0
  27. data/spec/solr_testdata_provider.rb +89 -0
  28. data/spec/spec_helper.rb +27 -0
  29. data/test-solr/.gitignore +4 -0
  30. data/test-solr/articles.xml +6 -0
  31. data/test-solr/etc/jetty.xml +227 -0
  32. data/test-solr/etc/webdefault.xml +410 -0
  33. data/test-solr/lib/jetty-6.1.26-patched-JETTY-1340.jar +0 -0
  34. data/test-solr/lib/jetty-LICENSE.txt +202 -0
  35. data/test-solr/lib/jetty-NOTICE.txt +36 -0
  36. data/test-solr/lib/jetty-util-6.1.26-patched-JETTY-1340.jar +0 -0
  37. data/test-solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
  38. data/test-solr/lib/jsp-2.1/jsp-2.1-glassfish-2.1.v20091210.jar +0 -0
  39. data/test-solr/lib/jsp-2.1/jsp-2.1-jetty-6.1.26.jar +0 -0
  40. data/test-solr/lib/jsp-2.1/jsp-api-2.1-glassfish-2.1.v20091210.jar +0 -0
  41. data/test-solr/lib/lukeall-3.4.0_1.jar +0 -0
  42. data/test-solr/lib/servlet-api-2.5-20081211.jar +0 -0
  43. data/test-solr/solr/lib/apache-solr-dataimporthandler-3.4.0.jar +0 -0
  44. data/test-solr/solr/solr.xml +20 -0
  45. data/test-solr/solr/testcore/conf/dataimport-test.xml +12 -0
  46. data/test-solr/solr/testcore/conf/schema.xml +42 -0
  47. data/test-solr/solr/testcore/conf/solr_schema.css +58 -0
  48. data/test-solr/solr/testcore/conf/solr_schema.xsl +72 -0
  49. data/test-solr/solr/testcore/conf/solrconfig.xml +72 -0
  50. data/test-solr/start-test-solr.sh +10 -0
  51. data/test-solr/start.jar +0 -0
  52. data/test-solr/webapps/solr.war +0 -0
  53. metadata +212 -0
@@ -0,0 +1,97 @@
1
+ # Filter für einfachen Wert mit Wertebereich als Collection
2
+ # und Darstellung als Select-Box.
3
+ # Der Wertebereich wird dabei über eine FacetSuche ermittelt (per Methode 'list_possible_values' des Searchers)
4
+ #
5
+ class MultiSolr::SolrFilterCollection < MultiSolr::SolrFilterSimple
6
+
7
+ # Constructor des Filters
8
+ # Params:
9
+ # filter_name: Name des Filters als Symbol
10
+ # options: optionale Hash mit den folgenden Optionen (sind alle optional):
11
+ # :render_value siehe Optionen bei MultiSolr::SolrFilterSimple.initialize
12
+ # :solr_query siehe Optionen bei MultiSolr::SolrFilterSimple.initialize
13
+ # :collection_data: Proc, welches den Wertebereich(Array) liefert
14
+ # Wenn nicht angegeben, dann wird per 'Searcher.list_possible_values'
15
+ # mit den Name des Filters der Wertebereich ermittelt.
16
+ # Das Proc bekommt den Such-Context(Hash) als Parameter (enthält i.a. Searcher und force-query-params).
17
+ # Beispiel: :collection_data => lambda{|context| (2..10).to_a }
18
+ # :after_collect: optionales Proc, welches den Wertebereich(Array) nachbearbeitet
19
+ # Das Proc bekommt den Wertebereich(Array) als Parameter
20
+ # Beispiel: :after_collect => lambda{|data| MasterData::LockType.cached_find_for_short_names(data).map{|l| [l.full_label, l.short_name] } }
21
+ #
22
+ def initialize filter_name, options={}
23
+ @collection_proc = options.delete(:collection_data)
24
+ @after_collect_proc = options.delete(:after_collect)
25
+ if options[:render_value].nil?
26
+ options[:render_value] = lambda{|value| compact_values(value).join(' oder ') }
27
+ end
28
+ if options[:solr_query].nil?
29
+ options[:solr_query] = lambda do |value|
30
+ if value.is_a?(Array)
31
+ values = compact_values(value)
32
+ if values.empty?
33
+ ''
34
+ else
35
+ q = values.map{|val| "#{@name}:#{val}"}.join(' OR ')
36
+ "(#{q})"
37
+ end
38
+ else
39
+ "#{@name}:#{value}"
40
+ end
41
+ end
42
+ end
43
+ super filter_name, options
44
+ end
45
+
46
+
47
+ # Generieren Select-Box für ein Sematic-Form
48
+ # Params: siehe MultiSolr::SolrFilterSimple#render_for_semantic_form
49
+ # returns: HTML-Code des Input-Feldes als Select-Box
50
+ def render_for_semantic_form sform, value, context=nil, form_input_options={}
51
+ form_input_options = @options[:semantic_form].merge form_input_options if @options.key? :semantic_form
52
+ set_label form_input_options
53
+ data = self.collection_data(nil, context)
54
+ html_options = form_input_options[:input_html]
55
+ if html_options
56
+ if html_options[:size]
57
+ # size wird als max-size verstanden. wenn akt. Data-Range kleiner
58
+ # ist, dann darauf reduzieren
59
+ html_options[:size] = [data.size+1, html_options[:size].to_i].min
60
+ end
61
+ end
62
+ form_input_options.merge! :collection => data
63
+ sform.input "filter_#{@name}", form_input_options
64
+ end
65
+
66
+
67
+ # Ermittelt den Wertebereich entweder über die bei den Options angegebene Proc
68
+ # oder über list_possible_values des Searchers (mit den Namen des Filters als Parameter)
69
+ # Params:
70
+ # core_handler: Instanz des konkreten Solr-CoreHandler (MultiSolr::SingleCoreHandler)
71
+ # context: Hash mit dem Such-Context.
72
+ # search_request: optional bestehendes SearchRequest (für DrillDown-Funktionalität)
73
+ # returns: Array mit dem Wertebereich
74
+ def collection_data core_handler, context, search_request=nil
75
+ if @collection_proc
76
+ data = @collection_proc.call(context)
77
+ else
78
+ data = core_handler.cached_list_possible_values(self.name, context, search_request)
79
+ end
80
+ if @after_collect_proc
81
+ data = @after_collect_proc.call(data)
82
+ data.compact!
83
+ end
84
+ data
85
+ end
86
+
87
+
88
+ # Wandeltangegebener value in ein Array (wenn es noch keins ist)
89
+ # Bereinigt das Array von leeren Elementen
90
+
91
+ def compact_values value
92
+ value = [value] unless value.is_a?(Array)
93
+ value.delete_if(&:blank?)
94
+ end
95
+
96
+ end
97
+
@@ -0,0 +1,46 @@
1
+ # Filter für Datumsbereiche mit von- und bis-Datum
2
+
3
+ class MultiSolr::SolrFilterDate < MultiSolr::SolrFilterSimple
4
+
5
+
6
+ # Constructor des Filters
7
+ # Params:
8
+ # filter_name: Name des Filters als Symbol
9
+ # options: optionale Hash mit Optionen (siehe SolrFilterSimple) plus:
10
+ # :mode Type der Nutzung des ang. Datums (Symbol):
11
+ # :from => Datum wird mit Zeit 00:00:00 genutzt
12
+ # :to => Datum wird mit Zeit 23:59:59 genutzt
13
+ # nil => Datum wird im Bereich 00:00:00 bis 23:59:59
14
+ #
15
+ def initialize filter_name, options={}
16
+ @mode = options.delete(:mode)
17
+ super(filter_name, options)
18
+ end
19
+
20
+
21
+ # Erzeugen des SolR-Query-Strings
22
+ def build_solr_query value
23
+ return nil if value.blank?
24
+ date_range = nil
25
+ case @mode
26
+ when :from
27
+ date_range = "[#{value}T00:00:00Z TO *]"
28
+ when :to
29
+ date_range = "[* TO #{value}T23:59:59Z]"
30
+ else
31
+ date_range = "[#{value}T00:00:00Z TO #{value}T23:59:59Z]"
32
+ end
33
+ "#{@field_name}:#{date_range}"
34
+ end
35
+
36
+
37
+ def render_value value
38
+ value.to_s
39
+ end
40
+
41
+
42
+ end
43
+
44
+
45
+
46
+
@@ -0,0 +1,62 @@
1
+ # Filter für Datumsbereiche mit von- und bis-Datum
2
+
3
+ class MultiSolr::SolrFilterDateRange < MultiSolr::SolrFilterSimple
4
+
5
+ # Erzeugen des SolR-Query-Strings
6
+ def build_solr_query value
7
+ from, to = extract_from_to_in_ISO8601 value
8
+ return nil if from.nil? && to.nil?
9
+ "#{@field_name}:[#{from || '*'} TO #{to || '*'}]"
10
+ end
11
+
12
+
13
+ def render_value value
14
+ from, to = extract_from_to value
15
+ return '' if from.nil? && to.nil?
16
+ s = []
17
+ s << "&gt;=#{from}" unless from.blank?
18
+ s << "&lt;=#{to}" unless to.blank?
19
+ s.join(' und ')
20
+ end
21
+
22
+
23
+ # Generieren der 2 Input-Felder mit der Option :as => :date_picker
24
+ # Dadurch können diesem Felder das jQuery-Datepicker-UI nutzen
25
+ # Params: siehe MultiSolr::SolrFilterSimple#render_for_semantic_form
26
+ # returns: HTML-Code mit 2 Input-Feldern
27
+ def render_for_semantic_form sform, value, context=nil, form_input_options={}
28
+ set_label form_input_options
29
+ label = form_input_options[:label]
30
+ form_input_options.merge! :as => :date_picker
31
+ from, to = extract_from_to value
32
+ date_range = Struct.new("#{@name}_from".to_sym, "#{@name}_to".to_sym).new from,to
33
+ sform.semantic_fields_for "filter_#{@name}", date_range do |filter_form|
34
+ form_input_options[:label] = "#{label} ab"
35
+ sform.template.concat filter_form.input("#{@name}_from", form_input_options)
36
+ form_input_options[:label] = "#{label} bis"
37
+ sform.template.concat filter_form.input("#{@name}_to", form_input_options)
38
+ end
39
+ end
40
+
41
+
42
+ # Aus dem 'value' von und bis extrahieren
43
+ # Params:
44
+ # value: Hash mit from- und to-Datumsangabe (mit Filternamen als Prefix)
45
+ # Beispiel: { 'create_date_from' => '2011-01-01', 'create_date_to' => '2011-06-01' }
46
+ # returns: Array mit von und bis ['2011-01-01', '2011-06-01']
47
+ def extract_from_to value
48
+ return nil if value.blank? || !value.is_a?(Hash) || value.empty?
49
+ [ value["#{@name}_from"], value["#{@name }_to"] ]
50
+ end
51
+
52
+ def extract_from_to_in_ISO8601 value
53
+ from, to = extract_from_to value
54
+ d_from = from.blank? ? nil : "#{from}T00:00:00Z"
55
+ d_to = to.blank? ? nil : "#{to}T23:59:59Z"
56
+ [d_from, d_to]
57
+ end
58
+ end
59
+
60
+
61
+
62
+
@@ -0,0 +1,11 @@
1
+ # Filter für eine freie Query-Eingabe die direkt so an den SOLR geht
2
+
3
+ class MultiSolr::SolrFilterFreeQuery < MultiSolr::SolrFilterSimple
4
+
5
+ def build_solr_query value
6
+ return nil if value.blank?
7
+ value
8
+ end
9
+
10
+ end
11
+
@@ -0,0 +1,96 @@
1
+ # Einfacher Solr-Filter mit einem String als Value
2
+ # Ist auch Basisklasse für alle erweiterten Filter
3
+
4
+ class MultiSolr::SolrFilterSimple
5
+
6
+ attr_reader :name # Name des Filters als Symbol
7
+ attr_reader :options # Options des Filters
8
+
9
+ # Constructor des Filters
10
+ # Params:
11
+ # filter_name: Name des Filters als Symbol
12
+ # options: optionale Hash mit den folgenden Optionen (sind alle optional):
13
+ # :render_value Proc welcher den Filter-Value in einem String zur Darstellung generiert
14
+ # Ist dieser nicht angegeben so wird 'value.to_s' benutzt
15
+ # Beispiel: :render_value => lambda{|value| ItemSize::HANDLINGS[value.to_i] }
16
+ # :field_name Name des zu nutzenden Solr-Fields, default ist filter_name
17
+ # :solr_query Proc welcher den SolR-Query-String mit den Filter-Value bildet.
18
+ # Wenn nicht angegeben wird <field_name>:<value> benutzt
19
+ # Beispiel: :solr_query => lambda{|value| "teileanzahl:[#{value} TO *]" }
20
+ #
21
+ def initialize name, options={}
22
+ @name = name
23
+ @field_name = options[:field_name] || @name
24
+ @value_render_proc = options.delete(:render_value) || lambda{|value| value.to_s }
25
+ @solr_query_proc = options.delete(:solr_query) || lambda{|value| "#{@field_name}:#{value}"}
26
+ @options = options || {}
27
+ end
28
+
29
+
30
+ # Bilden des SolR-Query-Strings entweder
31
+ # per bei der Erzeugung angegebenen solr-query-Proc
32
+ # oder aus Filter-Namen und dem spezifizierten 'value'
33
+ # Besteht der 'value' aus mehren Worten, so wird er automatisch in Hochkomma eingeschlossen
34
+ # ( 'test sample' => '"test sample"')
35
+ # Params:
36
+ # value: der konkrete Wert für diesen Filter
37
+ # returns: String in SOLR-Query-Syntax
38
+ def build_solr_query value
39
+ return nil if value.blank?
40
+ # wenn Leerzeichen vorkommen dann String in " einschliessen
41
+ value = "\"#{value}\"" if value =~ /\s+/
42
+ @solr_query_proc.call(value)
43
+ end
44
+
45
+
46
+ # Konvertieren der Wertes in den Darstellungs-String
47
+ # Nutzt wenn bei den Init-Options angegeben den hinterlegten Proc (value_render).
48
+ # Ansonsten wird nur 'value.to_s' aufgerufen.
49
+ # Params:
50
+ # value: der konkrete Wert für diesen Filter
51
+ # returns: String
52
+ def render_value value
53
+ return '' if value.nil?
54
+ @value_render_proc.call(value)
55
+ end
56
+
57
+
58
+
59
+
60
+ # Konvertieren der Wertes in HTML-String für ein Semantic-Form
61
+ # Params:
62
+ # sform: das Semantic-Form-Object
63
+ # value: der konkrete Wert für diesen Filter
64
+ # context: optionaler Hash mit dem Such-Context z.B. mit;
65
+ # :solr_searcher_class => Classe des konkreten Searchers
66
+ # :force_query_params => Parameter für die SolR-Force-Query
67
+ # form_input_options: optionale Formula-Input-Feld-Options.
68
+ # Diese werden 1:1 an die Semantic-Form-Methode 'input' weitergegeben
69
+ #
70
+ # returns: HTML-Code des Input-Feldes
71
+ def render_for_semantic_form sform, value, context=nil, form_input_options={}
72
+ form_input_options = @options[:semantic_form].merge form_input_options if @options.key? :semantic_form
73
+ set_label form_input_options
74
+ sform.input "filter_#{@name}", form_input_options
75
+ end
76
+
77
+
78
+ def label
79
+ I18n.t("solr_search.#{@name}", :default => @name.to_s)
80
+ end
81
+
82
+ protected
83
+
84
+ # Setzt in die angegebebn 'form_input_options' das Label (nur wenn in diesen noch kein :label definiert ist).
85
+ # Dieses wird gebildet aus den Filter-Namen unter Nutzung von I18n mit den Prefiy 'solr_search.'.
86
+ # Beispiel:
87
+ # filter-name = :lkz => I18n.t('solr_search.lkz')
88
+ def set_label form_input_options
89
+ form_input_options.merge!(:label => self.label) unless form_input_options.key?(:label)
90
+ end
91
+
92
+ end
93
+
94
+
95
+
96
+
@@ -0,0 +1,131 @@
1
+ require "fileutils"
2
+
3
+ class MultiSolr::TimelineCoreHandler
4
+
5
+ attr_reader :simple_core_handler_class
6
+ attr_reader :core_group_name
7
+ attr_reader :solr_url
8
+
9
+
10
+ def initialize solr_url, core_group_name, simple_core_handler_class
11
+ @simple_core_handler_class = simple_core_handler_class
12
+ @core_group_name = core_group_name
13
+ @solr_url = solr_url || raise("No solr-url given!")
14
+ end
15
+
16
+
17
+ def create_single_core_handler core_name=nil, options=nil
18
+ core_name ||= last_core_name
19
+ @simple_core_handler_class.new @solr_url, core_name, options
20
+ end
21
+
22
+
23
+
24
+ # Liefert Array mit den Namen der verfügbaren Cores, die mit dem Core-Namen (see core_name) beginnen
25
+ # Diese Liste wird gecached
26
+ def list_cores include_empties=false
27
+ return @cores if @cores
28
+ status = self.core_status
29
+ @cores = []
30
+ matcher = Regexp.new "^#{@core_group_name}"
31
+ status.each do |core_name, data|
32
+ next unless matcher.match(core_name)
33
+ next if data['index']['numDocs'] < 3 && !include_empties
34
+ @cores << core_name
35
+ end
36
+ @cores.sort!
37
+ MultiSolr.logger.info "MultiSolr::TimelineCoreHandler.list_cores: #{@cores.join(',')}"
38
+ @cores
39
+ end
40
+
41
+ # Rücksetzen Cache der core-liste (see list_cores)
42
+ def reset_cores
43
+ @cores = @last_core_name = nil
44
+ end
45
+
46
+ # Liefert Name des letzte Cores der laut alphabetischer Liste (see list_cores) existiert
47
+ def last_core_name
48
+ @last_core_name ||= list_cores.last
49
+ end
50
+
51
+ def base_connection
52
+ @_connection ||= RSolr.connect :url => @solr_url
53
+ end
54
+
55
+
56
+ def core_connection core_name=nil
57
+ core_name ||= last_core_name
58
+ RSolr.connect :url => "#{@solr_url}/#{core_name}"
59
+ end
60
+
61
+
62
+ def create_core suffix=nil
63
+ suffix = Time.now.strftime('%Y%m%d-%H%M') if suffix.nil?
64
+ new_core_name = "#{@core_group_name}-#{suffix}"
65
+ status = self.core_status last_core_name
66
+ old_name = status['name']
67
+ instance_dir_old = status['instanceDir']
68
+ instance_dir = instance_dir_old.sub(/^solr\//, '') # führendes solr im instanceDir ist zuviel, also entfernen
69
+ data_dir = status['dataDir'].sub(/#{old_name}\/$/, new_core_name)
70
+ data_dir.sub!(/^#{instance_dir_old}/, '')# führendes instanceDir im dataDir ist zuviel, also entfernen
71
+ res = self.base_connection.get 'admin/cores', :params => {:action => 'CREATE',
72
+ :name => new_core_name,
73
+ :instanceDir => instance_dir,
74
+ :dataDir => data_dir}
75
+ reset_cores
76
+ MultiSolr.logger.info "MultiSolr::TimelineCoreHandler.create_core: Core '#{new_core_name}' created. dataDir=#{data_dir}, instanceDir=#{instance_dir}"
77
+ new_core_name
78
+ end
79
+
80
+
81
+ def dataimport import_handler_name, command='full-import', core_name=nil
82
+ core_name ||= last_core_name
83
+ con = core_connection core_name
84
+ res = con.get import_handler_name, :params => {:command => command}
85
+ MultiSolr.logger.info "MultiSolr::TimelineCoreHandler.dataimport: core=#{core_name}, command=#{command}, handler=#{import_handler_name}"
86
+ res
87
+ end
88
+
89
+ # Entfernen angegebenen Core aus der Core-Liste inkl. unload-Befehl an den Solr
90
+ # Achtung! Diese Methode löscht kann nur dann die physischen Daten des Cores löschen,
91
+ # wenn dieser mit einer absoluten Pfad-Angabe im solr konfiguriert ist!
92
+ # Parameter:
93
+ # core_name: Name des zu löschenden Cores
94
+ # with_data: optionaler Angabe ob Daten mit gelöscht werden sollen (Standardmäßig aus)
95
+ def remove_core core_name, with_data=false
96
+ status = self.core_status core_name
97
+ raise "no core '#{core_name}'!" if status.nil? || status['name'].nil?
98
+ base_connection.get 'admin/cores', :params => {:action => 'unload', :core => core_name}
99
+ MultiSolr.logger.info "MultiSolr::TimelineCoreHandler.remove_core: Core '#{core_name}' unloaded"
100
+ if with_data
101
+ data_dir = status['dataDir']
102
+ raise "No absolute DataDir-Path! Only Core was unloaded!" unless data_dir.start_with?('/')
103
+ FileUtils.rm_rf data_dir
104
+ end
105
+ reset_cores
106
+ nil
107
+ end
108
+
109
+
110
+ # Liefert Core-Status evtl. aller Cores oder wenn Core-Name angegeben des einzelnen Cores
111
+ # returns Hash mit den Statusdaten
112
+ # Beispiel für alle Cores:
113
+ # {'core-01'=>{'name'=>'core-01',
114
+ # 'instanceDir'=>'solr/cobra-stock/',
115
+ # 'dataDir'=>'solr/cobra-stock/../../data/cobra-stock/',
116
+ # 'startTime'=>'2012-04-11T09:49:07.93Z',
117
+ # 'uptime'=>7796905,
118
+ # 'index'=>{'numDocs'=>1369046,'maxDoc'=>1369046,'version'=>1334134600492,'optimized'=>true,'current'=>true,'hasDeletions'=>false,'directory'=>'org.apache.lucene.store.NIOFSDirectory:org.apache.lucene.store.NIOFSDirectory@/home/bledig/Projects/lava/multi-solr/data/cobra-stock-20120411-1123/index lockFactory=org.apache.lucene.store.NativeFSLockFactory@1896a4c','lastModified'=>'2012-04-11T09:43:32Z'}},
119
+ # },...
120
+ # }
121
+ def core_status core_name=nil
122
+ params = {:action => 'STATUS' }
123
+ params[:core] = core_name if core_name
124
+ res = base_connection.get 'admin/cores', :params => params
125
+ status = res && res['status']
126
+ raise 'No status for cores available' if status.nil?
127
+ return status[core_name] if core_name
128
+ status
129
+ end
130
+
131
+ end
@@ -0,0 +1,3 @@
1
+ module MultiSolr
2
+ VERSION = "01.01.05"
3
+ end
data/lib/multi_solr.rb ADDED
@@ -0,0 +1,43 @@
1
+
2
+ require 'logger'
3
+ require 'active_support/cache'
4
+
5
+ require 'multi_solr/version'
6
+ require 'multi_solr/solr_filter_simple'
7
+ require 'multi_solr/solr_filter_collection'
8
+ require 'multi_solr/solr_filter_date'
9
+ require 'multi_solr/solr_filter_date_range'
10
+ require 'multi_solr/solr_filter_free_query'
11
+ require 'multi_solr/filter_value_composite'
12
+ require 'multi_solr/search_request'
13
+ require 'multi_solr/search_result'
14
+ require 'multi_solr/base_searcher'
15
+ require 'multi_solr/single_core_handler'
16
+ require 'multi_solr/timeline_core_handler'
17
+
18
+ module MultiSolr
19
+
20
+ @@logger = nil
21
+ @@cache = nil
22
+
23
+ def logger
24
+ return Rails.logger if defined? Rails
25
+ if @@logger.nil?
26
+ @@logger = Logger.new($stdout)
27
+ end
28
+ @@logger
29
+ end
30
+
31
+
32
+ def cache
33
+ return Rails.cache if defined? Rails
34
+ if @@cache.nil?
35
+ @@cache = ActiveSupport::Cache::MemoryStore.new
36
+ end
37
+ @@cache
38
+ end
39
+
40
+ module_function :logger, :cache
41
+
42
+ end
43
+
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "multi_solr/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "multi-solr"
7
+ s.version = MultiSolr::VERSION
8
+ s.authors = ["Bernd Ledig"]
9
+ s.email = ["bernd.ledig@ottogroup.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{SOLR-Framework with support for multiple SOLR-Cores}
12
+ s.description = %q{SOLR-Framework wit multi-core supoort and filters}
13
+
14
+ s.rubyforge_project = "multi-solr"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_runtime_dependency "rsolr", '>1.0', '<2.0'
23
+ s.add_runtime_dependency "activesupport", '>3.0', '<4.0'
24
+ s.add_runtime_dependency "i18n"
25
+
26
+ s.add_development_dependency "rake"
27
+ s.add_development_dependency "rspec", '>2.7', '<3.0'
28
+ end
@@ -0,0 +1,13 @@
1
+ ---
2
+ - id: 101
3
+ lager_id: 8
4
+ menge: 7
5
+ artikelnr: 124536
6
+ - id: 102
7
+ lager_id: 8
8
+ menge: 7
9
+ artikelnr: 847362
10
+ - id: 103
11
+ lager_id: 24
12
+ menge: 1
13
+ artikelnr: 895466