pduey-sunspot 1.2.1.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.
- data/.gitignore +12 -0
- data/Gemfile +5 -0
- data/History.txt +225 -0
- data/LICENSE +18 -0
- data/Rakefile +15 -0
- data/TODO +13 -0
- data/VERSION.yml +4 -0
- data/bin/sunspot-installer +19 -0
- data/installer/config/schema.yml +95 -0
- data/lib/light_config.rb +40 -0
- data/lib/sunspot.rb +568 -0
- data/lib/sunspot/adapters.rb +265 -0
- data/lib/sunspot/composite_setup.rb +202 -0
- data/lib/sunspot/configuration.rb +46 -0
- data/lib/sunspot/data_extractor.rb +50 -0
- data/lib/sunspot/dsl.rb +5 -0
- data/lib/sunspot/dsl/adjustable.rb +47 -0
- data/lib/sunspot/dsl/field_query.rb +279 -0
- data/lib/sunspot/dsl/fields.rb +103 -0
- data/lib/sunspot/dsl/fulltext.rb +243 -0
- data/lib/sunspot/dsl/function.rb +14 -0
- data/lib/sunspot/dsl/functional.rb +44 -0
- data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
- data/lib/sunspot/dsl/paginatable.rb +28 -0
- data/lib/sunspot/dsl/query_facet.rb +36 -0
- data/lib/sunspot/dsl/restriction.rb +25 -0
- data/lib/sunspot/dsl/restriction_with_near.rb +121 -0
- data/lib/sunspot/dsl/scope.rb +217 -0
- data/lib/sunspot/dsl/search.rb +30 -0
- data/lib/sunspot/dsl/standard_query.rb +121 -0
- data/lib/sunspot/field.rb +193 -0
- data/lib/sunspot/field_factory.rb +129 -0
- data/lib/sunspot/indexer.rb +131 -0
- data/lib/sunspot/installer.rb +31 -0
- data/lib/sunspot/installer/library_installer.rb +45 -0
- data/lib/sunspot/installer/schema_builder.rb +219 -0
- data/lib/sunspot/installer/solrconfig_updater.rb +76 -0
- data/lib/sunspot/installer/task_helper.rb +18 -0
- data/lib/sunspot/java.rb +8 -0
- data/lib/sunspot/query.rb +11 -0
- data/lib/sunspot/query/abstract_field_facet.rb +52 -0
- data/lib/sunspot/query/boost_query.rb +24 -0
- data/lib/sunspot/query/common_query.rb +85 -0
- data/lib/sunspot/query/composite_fulltext.rb +36 -0
- data/lib/sunspot/query/connective.rb +206 -0
- data/lib/sunspot/query/date_field_facet.rb +14 -0
- data/lib/sunspot/query/dismax.rb +128 -0
- data/lib/sunspot/query/field_facet.rb +41 -0
- data/lib/sunspot/query/filter.rb +38 -0
- data/lib/sunspot/query/function_query.rb +52 -0
- data/lib/sunspot/query/geo.rb +53 -0
- data/lib/sunspot/query/highlighting.rb +55 -0
- data/lib/sunspot/query/more_like_this.rb +61 -0
- data/lib/sunspot/query/more_like_this_query.rb +12 -0
- data/lib/sunspot/query/pagination.rb +38 -0
- data/lib/sunspot/query/query_facet.rb +16 -0
- data/lib/sunspot/query/restriction.rb +262 -0
- data/lib/sunspot/query/scope.rb +9 -0
- data/lib/sunspot/query/sort.rb +95 -0
- data/lib/sunspot/query/sort_composite.rb +33 -0
- data/lib/sunspot/query/standard_query.rb +16 -0
- data/lib/sunspot/query/text_field_boost.rb +17 -0
- data/lib/sunspot/schema.rb +151 -0
- data/lib/sunspot/search.rb +9 -0
- data/lib/sunspot/search/abstract_search.rb +335 -0
- data/lib/sunspot/search/date_facet.rb +35 -0
- data/lib/sunspot/search/facet_row.rb +27 -0
- data/lib/sunspot/search/field_facet.rb +88 -0
- data/lib/sunspot/search/highlight.rb +38 -0
- data/lib/sunspot/search/hit.rb +150 -0
- data/lib/sunspot/search/more_like_this_search.rb +31 -0
- data/lib/sunspot/search/paginated_collection.rb +55 -0
- data/lib/sunspot/search/query_facet.rb +67 -0
- data/lib/sunspot/search/standard_search.rb +21 -0
- data/lib/sunspot/session.rb +260 -0
- data/lib/sunspot/session_proxy.rb +87 -0
- data/lib/sunspot/session_proxy/abstract_session_proxy.rb +29 -0
- data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +66 -0
- data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +89 -0
- data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +43 -0
- data/lib/sunspot/session_proxy/sharding_session_proxy.rb +222 -0
- data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +42 -0
- data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +37 -0
- data/lib/sunspot/setup.rb +350 -0
- data/lib/sunspot/text_field_setup.rb +29 -0
- data/lib/sunspot/type.rb +372 -0
- data/lib/sunspot/util.rb +243 -0
- data/lib/sunspot/version.rb +3 -0
- data/pduey-sunspot.gemspec +38 -0
- data/script/console +10 -0
- data/spec/api/adapters_spec.rb +33 -0
- data/spec/api/binding_spec.rb +50 -0
- data/spec/api/indexer/attributes_spec.rb +149 -0
- data/spec/api/indexer/batch_spec.rb +46 -0
- data/spec/api/indexer/dynamic_fields_spec.rb +42 -0
- data/spec/api/indexer/fixed_fields_spec.rb +57 -0
- data/spec/api/indexer/fulltext_spec.rb +43 -0
- data/spec/api/indexer/removal_spec.rb +53 -0
- data/spec/api/indexer/spec_helper.rb +1 -0
- data/spec/api/indexer_spec.rb +14 -0
- data/spec/api/query/advanced_manipulation_examples.rb +35 -0
- data/spec/api/query/connectives_examples.rb +189 -0
- data/spec/api/query/dsl_spec.rb +18 -0
- data/spec/api/query/dynamic_fields_examples.rb +165 -0
- data/spec/api/query/faceting_examples.rb +397 -0
- data/spec/api/query/fulltext_examples.rb +313 -0
- data/spec/api/query/function_spec.rb +70 -0
- data/spec/api/query/geo_examples.rb +68 -0
- data/spec/api/query/highlighting_examples.rb +223 -0
- data/spec/api/query/more_like_this_spec.rb +140 -0
- data/spec/api/query/ordering_pagination_examples.rb +95 -0
- data/spec/api/query/scope_examples.rb +275 -0
- data/spec/api/query/spec_helper.rb +1 -0
- data/spec/api/query/standard_spec.rb +28 -0
- data/spec/api/query/text_field_scoping_examples.rb +30 -0
- data/spec/api/query/types_spec.rb +20 -0
- data/spec/api/search/dynamic_fields_spec.rb +33 -0
- data/spec/api/search/faceting_spec.rb +360 -0
- data/spec/api/search/highlighting_spec.rb +69 -0
- data/spec/api/search/hits_spec.rb +131 -0
- data/spec/api/search/paginated_collection_spec.rb +26 -0
- data/spec/api/search/results_spec.rb +66 -0
- data/spec/api/search/search_spec.rb +23 -0
- data/spec/api/search/spec_helper.rb +1 -0
- data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +85 -0
- data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +30 -0
- data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +41 -0
- data/spec/api/session_proxy/sharding_session_proxy_spec.rb +77 -0
- data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +24 -0
- data/spec/api/session_proxy/spec_helper.rb +9 -0
- data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +39 -0
- data/spec/api/session_spec.rb +220 -0
- data/spec/api/spec_helper.rb +3 -0
- data/spec/api/sunspot_spec.rb +18 -0
- data/spec/ext.rb +11 -0
- data/spec/helpers/indexer_helper.rb +29 -0
- data/spec/helpers/query_helper.rb +38 -0
- data/spec/helpers/search_helper.rb +80 -0
- data/spec/integration/dynamic_fields_spec.rb +57 -0
- data/spec/integration/faceting_spec.rb +238 -0
- data/spec/integration/highlighting_spec.rb +24 -0
- data/spec/integration/indexing_spec.rb +33 -0
- data/spec/integration/keyword_search_spec.rb +317 -0
- data/spec/integration/local_search_spec.rb +64 -0
- data/spec/integration/more_like_this_spec.rb +43 -0
- data/spec/integration/scoped_search_spec.rb +354 -0
- data/spec/integration/spec_helper.rb +7 -0
- data/spec/integration/stored_fields_spec.rb +12 -0
- data/spec/integration/test_pagination.rb +32 -0
- data/spec/mocks/adapters.rb +32 -0
- data/spec/mocks/blog.rb +3 -0
- data/spec/mocks/comment.rb +21 -0
- data/spec/mocks/connection.rb +126 -0
- data/spec/mocks/mock_adapter.rb +30 -0
- data/spec/mocks/mock_class_sharding_session_proxy.rb +24 -0
- data/spec/mocks/mock_record.rb +52 -0
- data/spec/mocks/mock_sharding_session_proxy.rb +15 -0
- data/spec/mocks/photo.rb +11 -0
- data/spec/mocks/post.rb +85 -0
- data/spec/mocks/super_class.rb +2 -0
- data/spec/mocks/user.rb +13 -0
- data/spec/spec_helper.rb +28 -0
- data/tasks/rdoc.rake +27 -0
- data/tasks/schema.rake +19 -0
- data/tasks/todo.rake +4 -0
- metadata +369 -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
|
data/lib/sunspot/java.rb
ADDED
|
@@ -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
|