lisausa-sunspot 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +4 -0
  3. data/History.txt +222 -0
  4. data/LICENSE +18 -0
  5. data/Rakefile +17 -0
  6. data/TODO +13 -0
  7. data/VERSION.yml +4 -0
  8. data/bin/sunspot-installer +19 -0
  9. data/bin/sunspot-solr +74 -0
  10. data/installer/config/schema.yml +95 -0
  11. data/lib/light_config.rb +40 -0
  12. data/lib/sunspot.rb +569 -0
  13. data/lib/sunspot/adapters.rb +265 -0
  14. data/lib/sunspot/composite_setup.rb +202 -0
  15. data/lib/sunspot/configuration.rb +46 -0
  16. data/lib/sunspot/data_extractor.rb +50 -0
  17. data/lib/sunspot/dsl.rb +5 -0
  18. data/lib/sunspot/dsl/adjustable.rb +47 -0
  19. data/lib/sunspot/dsl/field_query.rb +279 -0
  20. data/lib/sunspot/dsl/fields.rb +103 -0
  21. data/lib/sunspot/dsl/fulltext.rb +243 -0
  22. data/lib/sunspot/dsl/function.rb +14 -0
  23. data/lib/sunspot/dsl/functional.rb +44 -0
  24. data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
  25. data/lib/sunspot/dsl/paginatable.rb +28 -0
  26. data/lib/sunspot/dsl/query_facet.rb +36 -0
  27. data/lib/sunspot/dsl/restriction.rb +25 -0
  28. data/lib/sunspot/dsl/restriction_with_near.rb +121 -0
  29. data/lib/sunspot/dsl/scope.rb +217 -0
  30. data/lib/sunspot/dsl/search.rb +30 -0
  31. data/lib/sunspot/dsl/standard_query.rb +121 -0
  32. data/lib/sunspot/field.rb +193 -0
  33. data/lib/sunspot/field_factory.rb +129 -0
  34. data/lib/sunspot/indexer.rb +131 -0
  35. data/lib/sunspot/installer.rb +31 -0
  36. data/lib/sunspot/installer/library_installer.rb +45 -0
  37. data/lib/sunspot/installer/schema_builder.rb +219 -0
  38. data/lib/sunspot/installer/solrconfig_updater.rb +76 -0
  39. data/lib/sunspot/installer/task_helper.rb +18 -0
  40. data/lib/sunspot/query.rb +11 -0
  41. data/lib/sunspot/query/abstract_field_facet.rb +52 -0
  42. data/lib/sunspot/query/boost_query.rb +24 -0
  43. data/lib/sunspot/query/common_query.rb +85 -0
  44. data/lib/sunspot/query/composite_fulltext.rb +36 -0
  45. data/lib/sunspot/query/connective.rb +206 -0
  46. data/lib/sunspot/query/date_field_facet.rb +14 -0
  47. data/lib/sunspot/query/dismax.rb +128 -0
  48. data/lib/sunspot/query/field_facet.rb +41 -0
  49. data/lib/sunspot/query/filter.rb +38 -0
  50. data/lib/sunspot/query/function_query.rb +52 -0
  51. data/lib/sunspot/query/geo.rb +53 -0
  52. data/lib/sunspot/query/highlighting.rb +67 -0
  53. data/lib/sunspot/query/more_like_this.rb +61 -0
  54. data/lib/sunspot/query/more_like_this_query.rb +12 -0
  55. data/lib/sunspot/query/pagination.rb +38 -0
  56. data/lib/sunspot/query/query_facet.rb +16 -0
  57. data/lib/sunspot/query/restriction.rb +262 -0
  58. data/lib/sunspot/query/scope.rb +9 -0
  59. data/lib/sunspot/query/sort.rb +95 -0
  60. data/lib/sunspot/query/sort_composite.rb +33 -0
  61. data/lib/sunspot/query/standard_query.rb +16 -0
  62. data/lib/sunspot/query/text_field_boost.rb +17 -0
  63. data/lib/sunspot/schema.rb +151 -0
  64. data/lib/sunspot/search.rb +9 -0
  65. data/lib/sunspot/search/abstract_search.rb +293 -0
  66. data/lib/sunspot/search/date_facet.rb +35 -0
  67. data/lib/sunspot/search/facet_row.rb +27 -0
  68. data/lib/sunspot/search/field_facet.rb +88 -0
  69. data/lib/sunspot/search/highlight.rb +38 -0
  70. data/lib/sunspot/search/hit.rb +136 -0
  71. data/lib/sunspot/search/more_like_this_search.rb +31 -0
  72. data/lib/sunspot/search/paginated_collection.rb +55 -0
  73. data/lib/sunspot/search/query_facet.rb +67 -0
  74. data/lib/sunspot/search/standard_search.rb +21 -0
  75. data/lib/sunspot/server.rb +152 -0
  76. data/lib/sunspot/session.rb +260 -0
  77. data/lib/sunspot/session_proxy.rb +87 -0
  78. data/lib/sunspot/session_proxy/abstract_session_proxy.rb +29 -0
  79. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +66 -0
  80. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +89 -0
  81. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +43 -0
  82. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +222 -0
  83. data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +42 -0
  84. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +37 -0
  85. data/lib/sunspot/setup.rb +350 -0
  86. data/lib/sunspot/text_field_setup.rb +29 -0
  87. data/lib/sunspot/type.rb +372 -0
  88. data/lib/sunspot/util.rb +243 -0
  89. data/lib/sunspot/version.rb +3 -0
  90. data/script/console +10 -0
  91. data/solr-1.3/etc/jetty.xml +212 -0
  92. data/solr-1.3/etc/webdefault.xml +379 -0
  93. data/solr-1.3/lib/jetty-6.1.3.jar +0 -0
  94. data/solr-1.3/lib/jetty-util-6.1.3.jar +0 -0
  95. data/solr-1.3/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  96. data/solr-1.3/lib/jsp-2.1/core-3.1.1.jar +0 -0
  97. data/solr-1.3/lib/jsp-2.1/jsp-2.1.jar +0 -0
  98. data/solr-1.3/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  99. data/solr-1.3/lib/servlet-api-2.5-6.1.3.jar +0 -0
  100. data/solr-1.3/solr/conf/elevate.xml +36 -0
  101. data/solr-1.3/solr/conf/protwords.txt +21 -0
  102. data/solr-1.3/solr/conf/schema.xml +64 -0
  103. data/solr-1.3/solr/conf/solrconfig.xml +725 -0
  104. data/solr-1.3/solr/conf/stopwords.txt +57 -0
  105. data/solr-1.3/solr/conf/synonyms.txt +31 -0
  106. data/solr-1.3/solr/lib/geoapi-nogenerics-2.1-M2.jar +0 -0
  107. data/solr-1.3/solr/lib/gt2-referencing-2.3.1.jar +0 -0
  108. data/solr-1.3/solr/lib/jsr108-0.01.jar +0 -0
  109. data/solr-1.3/solr/lib/locallucene.jar +0 -0
  110. data/solr-1.3/solr/lib/localsolr.jar +0 -0
  111. data/solr-1.3/start.jar +0 -0
  112. data/solr-1.3/webapps/solr.war +0 -0
  113. data/solr/README.txt +42 -0
  114. data/solr/etc/jetty.xml +218 -0
  115. data/solr/etc/webdefault.xml +379 -0
  116. data/solr/lib/jetty-6.1.3.jar +0 -0
  117. data/solr/lib/jetty-util-6.1.3.jar +0 -0
  118. data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  119. data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
  120. data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
  121. data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  122. data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
  123. data/solr/solr/.gitignore +1 -0
  124. data/solr/solr/README.txt +54 -0
  125. data/solr/solr/conf/admin-extra.html +31 -0
  126. data/solr/solr/conf/elevate.xml +36 -0
  127. data/solr/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  128. data/solr/solr/conf/protwords.txt +21 -0
  129. data/solr/solr/conf/schema.xml +238 -0
  130. data/solr/solr/conf/scripts.conf +24 -0
  131. data/solr/solr/conf/solrconfig.xml +934 -0
  132. data/solr/solr/conf/spellings.txt +2 -0
  133. data/solr/solr/conf/stopwords.txt +58 -0
  134. data/solr/solr/conf/synonyms.txt +31 -0
  135. data/solr/solr/conf/xslt/example.xsl +132 -0
  136. data/solr/solr/conf/xslt/example_atom.xsl +67 -0
  137. data/solr/solr/conf/xslt/example_rss.xsl +66 -0
  138. data/solr/solr/conf/xslt/luke.xsl +337 -0
  139. data/solr/start.jar +0 -0
  140. data/solr/webapps/solr.war +0 -0
  141. data/spec/api/adapters_spec.rb +33 -0
  142. data/spec/api/binding_spec.rb +50 -0
  143. data/spec/api/indexer/attributes_spec.rb +149 -0
  144. data/spec/api/indexer/batch_spec.rb +46 -0
  145. data/spec/api/indexer/dynamic_fields_spec.rb +42 -0
  146. data/spec/api/indexer/fixed_fields_spec.rb +57 -0
  147. data/spec/api/indexer/fulltext_spec.rb +43 -0
  148. data/spec/api/indexer/removal_spec.rb +53 -0
  149. data/spec/api/indexer/spec_helper.rb +1 -0
  150. data/spec/api/indexer_spec.rb +14 -0
  151. data/spec/api/query/advanced_manipulation_examples.rb +35 -0
  152. data/spec/api/query/connectives_examples.rb +189 -0
  153. data/spec/api/query/dsl_spec.rb +18 -0
  154. data/spec/api/query/dynamic_fields_examples.rb +165 -0
  155. data/spec/api/query/faceting_examples.rb +397 -0
  156. data/spec/api/query/fulltext_examples.rb +313 -0
  157. data/spec/api/query/function_spec.rb +70 -0
  158. data/spec/api/query/geo_examples.rb +68 -0
  159. data/spec/api/query/highlighting_examples.rb +223 -0
  160. data/spec/api/query/more_like_this_spec.rb +140 -0
  161. data/spec/api/query/ordering_pagination_examples.rb +95 -0
  162. data/spec/api/query/scope_examples.rb +275 -0
  163. data/spec/api/query/spec_helper.rb +1 -0
  164. data/spec/api/query/standard_spec.rb +28 -0
  165. data/spec/api/query/text_field_scoping_examples.rb +30 -0
  166. data/spec/api/query/types_spec.rb +20 -0
  167. data/spec/api/search/dynamic_fields_spec.rb +33 -0
  168. data/spec/api/search/faceting_spec.rb +360 -0
  169. data/spec/api/search/highlighting_spec.rb +69 -0
  170. data/spec/api/search/hits_spec.rb +120 -0
  171. data/spec/api/search/paginated_collection_spec.rb +26 -0
  172. data/spec/api/search/results_spec.rb +66 -0
  173. data/spec/api/search/search_spec.rb +23 -0
  174. data/spec/api/search/spec_helper.rb +1 -0
  175. data/spec/api/server_spec.rb +91 -0
  176. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +85 -0
  177. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +30 -0
  178. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +41 -0
  179. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +77 -0
  180. data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +24 -0
  181. data/spec/api/session_proxy/spec_helper.rb +9 -0
  182. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +50 -0
  183. data/spec/api/session_spec.rb +220 -0
  184. data/spec/api/spec_helper.rb +3 -0
  185. data/spec/api/sunspot_spec.rb +18 -0
  186. data/spec/ext.rb +11 -0
  187. data/spec/helpers/indexer_helper.rb +29 -0
  188. data/spec/helpers/query_helper.rb +38 -0
  189. data/spec/helpers/search_helper.rb +80 -0
  190. data/spec/integration/dynamic_fields_spec.rb +55 -0
  191. data/spec/integration/faceting_spec.rb +238 -0
  192. data/spec/integration/highlighting_spec.rb +22 -0
  193. data/spec/integration/indexing_spec.rb +33 -0
  194. data/spec/integration/keyword_search_spec.rb +317 -0
  195. data/spec/integration/local_search_spec.rb +64 -0
  196. data/spec/integration/more_like_this_spec.rb +43 -0
  197. data/spec/integration/scoped_search_spec.rb +354 -0
  198. data/spec/integration/spec_helper.rb +7 -0
  199. data/spec/integration/stored_fields_spec.rb +10 -0
  200. data/spec/integration/test_pagination.rb +32 -0
  201. data/spec/mocks/adapters.rb +32 -0
  202. data/spec/mocks/blog.rb +3 -0
  203. data/spec/mocks/comment.rb +21 -0
  204. data/spec/mocks/connection.rb +126 -0
  205. data/spec/mocks/mock_adapter.rb +30 -0
  206. data/spec/mocks/mock_class_sharding_session_proxy.rb +24 -0
  207. data/spec/mocks/mock_record.rb +52 -0
  208. data/spec/mocks/mock_sharding_session_proxy.rb +15 -0
  209. data/spec/mocks/photo.rb +11 -0
  210. data/spec/mocks/post.rb +85 -0
  211. data/spec/mocks/super_class.rb +2 -0
  212. data/spec/mocks/user.rb +13 -0
  213. data/spec/spec_helper.rb +30 -0
  214. data/tasks/rdoc.rake +27 -0
  215. data/tasks/schema.rake +19 -0
  216. data/tasks/todo.rake +4 -0
  217. metadata +457 -0
@@ -0,0 +1,31 @@
1
+ %w(task_helper library_installer schema_builder solrconfig_updater).each do |file|
2
+ require File.join(File.dirname(__FILE__), 'installer', file)
3
+ end
4
+
5
+ module Sunspot
6
+ class Installer
7
+ class <<self
8
+ def execute(solr_home, options = {})
9
+ new(solr_home, options).execute
10
+ end
11
+
12
+ private :new
13
+ end
14
+
15
+ def initialize(solr_home, options)
16
+ @solr_home, @options = solr_home, options
17
+ end
18
+
19
+ def execute
20
+ SchemaBuilder.execute(
21
+ File.join(@solr_home, 'conf', 'schema.xml'),
22
+ @options
23
+ )
24
+ SolrconfigUpdater.execute(
25
+ File.join(@solr_home, 'conf', 'solrconfig.xml'),
26
+ @options
27
+ )
28
+ LibraryInstaller.execute(File.join(@solr_home, 'lib'), @options)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ require 'fileutils'
2
+
3
+ module Sunspot
4
+ class Installer
5
+ class LibraryInstaller
6
+ class <<self
7
+ def execute(library_path, options)
8
+ new(library_path, options).execute
9
+ end
10
+ end
11
+
12
+ def initialize(library_path, options)
13
+ @library_path = library_path
14
+ @verbose = !!options[:verbose]
15
+ @force = !!options[:force]
16
+ end
17
+
18
+ def execute
19
+ sunspot_library_path = File.join(File.dirname(__FILE__), '..', '..',
20
+ '..', 'solr', 'solr', 'lib')
21
+ return if File.expand_path(sunspot_library_path) == File.expand_path(@library_path)
22
+ FileUtils.mkdir_p(@library_path)
23
+ Dir.glob(File.join(sunspot_library_path, '*.jar')).each do |jar|
24
+ jar = File.expand_path(jar)
25
+ dest = File.join(@library_path, File.basename(jar))
26
+ if File.exist?(dest)
27
+ if @force
28
+ say("Removing existing library #{dest}")
29
+ else
30
+ next
31
+ end
32
+ end
33
+ say("Copying #{jar} => #{dest}")
34
+ FileUtils.cp(jar, dest)
35
+ end
36
+ end
37
+
38
+ def say(message)
39
+ if @verbose
40
+ STDOUT.puts(message)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,219 @@
1
+ require 'yaml'
2
+ require 'rexml/rexml'
3
+ require 'rexml/document'
4
+ require 'fileutils'
5
+
6
+ module Sunspot
7
+ class Installer
8
+ #
9
+ # This class modifies an existing Solr schema.xml file to work with Sunspot.
10
+ # It makes the minimum necessary changes to the schema, adding fields and
11
+ # types only when they don't already exist. It also comments all fields and
12
+ # types that Sunspot needs, whether or not they were preexisting, so that
13
+ # users can modify the resulting schema without unwittingly breaking it.
14
+ #
15
+ class SchemaBuilder
16
+ include TaskHelper
17
+
18
+ CONFIG_PATH = File.join(
19
+ File.dirname(__FILE__), '..', '..', '..', 'installer', 'config', 'schema.yml'
20
+ )
21
+
22
+ class <<self
23
+ def execute(schema_path, options = {})
24
+ new(schema_path, options).execute
25
+ end
26
+
27
+ private :new
28
+ end
29
+
30
+ def initialize(schema_path, options = {})
31
+ @schema_path = schema_path
32
+ @config = File.open(CONFIG_PATH) { |f| YAML.load(f) }
33
+ @verbose = !!options[:verbose]
34
+ @force = !!options[:force]
35
+ end
36
+
37
+ def execute
38
+ if @force
39
+ FileUtils.mkdir_p(File.dirname(@schema_path))
40
+ source_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'solr', 'solr', 'conf', 'schema.xml')
41
+ FileUtils.cp(source_path, @schema_path)
42
+ say("Copied default schema.xml to #{@schema_path}")
43
+ else
44
+ @document = File.open(@schema_path) do |f|
45
+ Nokogiri::XML(
46
+ f, nil, nil,
47
+ Nokogiri::XML::ParseOptions::DEFAULT_XML |
48
+ Nokogiri::XML::ParseOptions::NOBLANKS
49
+ )
50
+ end
51
+ @root = @document.root
52
+ @added_types = Set[]
53
+ add_fixed_fields
54
+ add_dynamic_fields
55
+ set_misc_settings
56
+ original_path = "#{@schema_path}.orig"
57
+ FileUtils.cp(@schema_path, original_path)
58
+ say("Saved backup of original to #{original_path}")
59
+ File.open(@schema_path, 'w') do |file|
60
+ @document.write_xml_to(file, :indent => 2)
61
+ end
62
+ say("Wrote schema to #{@schema_path}")
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def add_fixed_fields
69
+ @config['fixed'].each do |name, options|
70
+ maybe_add_field(name, options['type'], :indexed, *Array(options['attributes']))
71
+ end
72
+ end
73
+
74
+ def add_dynamic_fields
75
+ @config['types'].each do |type, options|
76
+ if suffix = options['suffix']
77
+ variant_combinations(options).each do |variants|
78
+ variants_suffix = variants.map { |variant| variant[1] || '' }.join
79
+ maybe_add_field("*_#{suffix}#{variants_suffix}", type, *variants.map { |variant| variant[0] })
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ def maybe_add_field(name, type, *flags)
86
+ node_name = name =~ /\*/ ? 'dynamicField' : 'field'
87
+ if field_node = fields_node.xpath(%Q(#{node_name}[@name="#{name}"])).first
88
+ say("Using existing #{node_name} #{name.inspect}")
89
+ add_comment(field_node)
90
+ return
91
+ end
92
+ maybe_add_type(type)
93
+ say("Adding field #{name.inspect}")
94
+ attributes = {
95
+ 'name' => name,
96
+ 'type' => type,
97
+ 'indexed' => 'true',
98
+ 'stored' => 'false',
99
+ 'multiValued' => 'false'
100
+ }
101
+ flags.each do |flag|
102
+ attributes[flag.to_s] = 'true'
103
+ end
104
+ field_node = add_element(fields_node, node_name, attributes)
105
+ add_comment(field_node)
106
+ end
107
+
108
+ def maybe_add_type(type)
109
+ unless @added_types.include?(type)
110
+ @added_types << type
111
+ if type_node = types_node.xpath(%Q(fieldType[@name="#{type}"])).first ||
112
+ types_node.xpath(%Q(fieldtype[@name="#{type}"])).first
113
+ say("Using existing type #{type.inspect}")
114
+ add_comment(type_node)
115
+ return
116
+ end
117
+ say("Adding type #{type.inspect}")
118
+ type_config = @config['types'][type]
119
+ type_node = add_element(
120
+ types_node,
121
+ 'fieldType',
122
+ 'name' => type,
123
+ 'class' => to_solr_class(type_config['class']),
124
+ 'omitNorms' => type_config['omit_norms'].nil? ? 'true' : type_config['omit_norms'].to_s
125
+ )
126
+ if type_config['tokenizer']
127
+ add_analyzer(type_node, type_config)
128
+ end
129
+ add_comment(type_node)
130
+ end
131
+ end
132
+
133
+ def add_analyzer(node, config)
134
+ analyzer_node = add_element(node, 'analyzer')
135
+ add_element(
136
+ analyzer_node,
137
+ 'tokenizer',
138
+ 'class' => to_solr_class(config['tokenizer'])
139
+ )
140
+ Array(config['filters']).each do |filter|
141
+ add_element(analyzer_node, 'filter', 'class' => to_solr_class(filter))
142
+ end
143
+ end
144
+
145
+ def set_misc_settings
146
+ if @root.xpath('uniqueKey[normalize-space()="id"]').any?
147
+ say('Unique key already set')
148
+ else
149
+ say("Creating unique key node")
150
+ add_element(@root, 'uniqueKey').content = 'id'
151
+ end
152
+ say('Setting default operator to AND')
153
+ solr_query_parser_node = @root.xpath('solrQueryParser').first ||
154
+ add_element(@root, 'solrQueryParser')
155
+ solr_query_parser_node['defaultOperator'] = 'AND'
156
+ end
157
+
158
+ def add_comment(node)
159
+ comment_message = " *** This #{node.name} is used by Sunspot! *** "
160
+ unless (comment = previous_non_text_sibling(node)) && comment.comment? && comment.content =~ /Sunspot/
161
+ node.add_previous_sibling(Nokogiri::XML::Comment.new(@document, comment_message))
162
+ end
163
+ end
164
+
165
+ def types_node
166
+ @types_node ||= @root.xpath('/schema/types').first
167
+ end
168
+
169
+ def fields_node
170
+ @fields_node ||= @root.xpath('/schema/fields').first
171
+ end
172
+
173
+ def to_solr_class(class_name)
174
+ if class_name =~ /\./
175
+ class_name
176
+ else
177
+ "solr.#{class_name}"
178
+ end
179
+ end
180
+
181
+ def previous_non_text_sibling(node)
182
+ if previous_sibling = node.previous_sibling
183
+ if previous_sibling.node_type == :text
184
+ previous_non_text_sibling(previous_sibling)
185
+ else
186
+ previous_sibling
187
+ end
188
+ end
189
+ end
190
+
191
+ #
192
+ # All of the possible combinations of variants
193
+ #
194
+ def variant_combinations(type_options)
195
+ invariants = type_options['invariants'] || {}
196
+ combinations = []
197
+ variants = @config['variants'].reject { |name, suffix| invariants.has_key?(name) }
198
+ 0.upto(2 ** variants.length - 1) do |b|
199
+ combinations << combination = []
200
+ variants.each_with_index do |variant, i|
201
+ combination << variant if b & 1<<i > 0
202
+ end
203
+ invariants.each do |name, value|
204
+ if value
205
+ combination << [name]
206
+ end
207
+ end
208
+ end
209
+ combinations
210
+ end
211
+
212
+ def say(message)
213
+ if @verbose
214
+ STDOUT.puts(message)
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,76 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+ require 'nokogiri'
4
+
5
+ module Sunspot
6
+ class Installer
7
+ class SolrconfigUpdater
8
+ include TaskHelper
9
+
10
+ CONFIG_FILES = %w(solrconfig.xml elevate.xml spellings.txt stopwords.txt synonyms.txt)
11
+
12
+ class <<self
13
+ def execute(solrconfig_path, options = {})
14
+ new(solrconfig_path, options).execute
15
+ end
16
+ end
17
+
18
+ def initialize(solrconfig_path, options)
19
+ @force = !!options[:force]
20
+ unless @force || File.exist?(solrconfig_path)
21
+ abort("#{File.expand_path(@solrconfig_path)} doesn't exist." +
22
+ " Are you sure you're pointing to a SOLR_HOME?")
23
+ end
24
+ @solrconfig_path = solrconfig_path
25
+ @verbose = !!options[:verbose]
26
+ end
27
+
28
+ def execute
29
+ if @force
30
+ config_dir = File.dirname(@solrconfig_path)
31
+ FileUtils.mkdir_p(config_dir)
32
+ CONFIG_FILES.each do |file|
33
+ source_path =
34
+ File.join(File.dirname(__FILE__), '..', '..', '..', 'solr', 'solr', 'conf', file)
35
+ FileUtils.cp(source_path, config_dir)
36
+ say("Copied default #{file} to #{config_dir}")
37
+ end
38
+ else
39
+ @document = File.open(@solrconfig_path) do |f|
40
+ Nokogiri::XML(
41
+ f, nil, nil,
42
+ Nokogiri::XML::ParseOptions::DEFAULT_XML |
43
+ Nokogiri::XML::ParseOptions::NOBLANKS
44
+ )
45
+ end
46
+ @root = @document.root
47
+ maybe_add_more_like_this_handler
48
+ original_path = "#{@solrconfig_path}.orig"
49
+ FileUtils.cp(@solrconfig_path, original_path)
50
+ say("Saved backup of original to #{original_path}")
51
+ File.open(@solrconfig_path, 'w') do |file|
52
+ @document.write_to(
53
+ file,
54
+ :indent => 2
55
+ )
56
+ end
57
+ say("Wrote solrconfig to #{@solrconfig_path}")
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def maybe_add_more_like_this_handler
64
+ unless @root.xpath('requestHandler[@name="/mlt"]').first
65
+ mlt_node = add_element(
66
+ @root, 'requestHandler',
67
+ :name => '/mlt', :class => 'solr.MoreLikeThisHandler'
68
+ )
69
+ defaults_node = add_element(mlt_node, 'lst', :name => 'defaults')
70
+ add_element(defaults_node, 'str', :name => 'mlt.mintf').content = '1'
71
+ add_element(defaults_node, 'str', :name => 'mlt.mindf').content = '2'
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,18 @@
1
+ module Sunspot
2
+ class Installer
3
+ module TaskHelper
4
+ def say(message)
5
+ if @verbose
6
+ STDOUT.puts(message)
7
+ end
8
+ end
9
+
10
+ def add_element(node, name, attributes = {})
11
+ new_node = Nokogiri::XML::Node.new(name, @document)
12
+ attributes.each_pair { |name, value| new_node[name.to_s] = value }
13
+ node << new_node
14
+ new_node
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ %w(filter abstract_field_facet connective boost_query date_field_facet dismax
2
+ field_facet highlighting pagination restriction common_query
3
+ standard_query more_like_this more_like_this_query geo query_facet scope
4
+ sort sort_composite text_field_boost function_query
5
+ composite_fulltext).each do |file|
6
+ require(File.join(File.dirname(__FILE__), 'query', file))
7
+ end
8
+ module Sunspot
9
+ module Query #:nodoc:all
10
+ end
11
+ end
@@ -0,0 +1,52 @@
1
+ module Sunspot
2
+ module Query
3
+ class AbstractFieldFacet
4
+ include RSolr::Char
5
+
6
+ def initialize(field, options)
7
+ @field, @options = field, options
8
+ end
9
+
10
+ def to_params
11
+ params = {
12
+ :facet => 'true',
13
+ }
14
+ case @options[:sort]
15
+ when :count
16
+ params[qualified_param('sort')] = 'true'
17
+ when :index
18
+ params[qualified_param('sort')] = 'false'
19
+ when nil
20
+ else
21
+ raise(
22
+ ArgumentError,
23
+ "#{@options[:sort].inspect} is not an allowed value for :sort. Allowed options are :count and :index"
24
+ )
25
+ end
26
+ if @options[:limit]
27
+ params[qualified_param('limit')] = @options[:limit].to_i
28
+ end
29
+ if @options[:prefix]
30
+ params[qualified_param('prefix')] = escape(@options[:prefix].to_s)
31
+ end
32
+ params[qualified_param('mincount')] =
33
+ case
34
+ when @options[:minimum_count] then @options[:minimum_count].to_i
35
+ when @options[:zeros] then 0
36
+ else 1
37
+ end
38
+ params
39
+ end
40
+
41
+ private
42
+
43
+ def qualified_param(param)
44
+ :"f.#{key}.facet.#{param}"
45
+ end
46
+
47
+ def key
48
+ @key ||= @options[:name] || @field.indexed_name
49
+ end
50
+ end
51
+ end
52
+ end