kuahyeow-sunspot 0.9.8 → 0.10.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +38 -0
- data/README.rdoc +40 -3
- data/TODO +10 -8
- data/VERSION.yml +2 -2
- data/bin/sunspot-configure-solr +22 -28
- data/bin/sunspot-solr +50 -29
- data/lib/sunspot.rb +8 -18
- data/lib/sunspot/adapters.rb +1 -1
- data/lib/sunspot/composite_setup.rb +13 -15
- data/lib/sunspot/configuration.rb +21 -0
- data/lib/sunspot/data_extractor.rb +3 -0
- data/lib/sunspot/dsl.rb +2 -1
- data/lib/sunspot/dsl/field_query.rb +33 -6
- data/lib/sunspot/dsl/fields.rb +14 -1
- data/lib/sunspot/dsl/fulltext.rb +168 -0
- data/lib/sunspot/dsl/query.rb +82 -5
- data/lib/sunspot/dsl/query_facet.rb +3 -3
- data/lib/sunspot/dsl/restriction.rb +7 -7
- data/lib/sunspot/dsl/scope.rb +17 -10
- data/lib/sunspot/dsl/search.rb +2 -2
- data/lib/sunspot/facet.rb +12 -39
- data/lib/sunspot/facet_data.rb +169 -0
- data/lib/sunspot/facet_row.rb +5 -27
- data/lib/sunspot/field.rb +50 -26
- data/lib/sunspot/field_factory.rb +15 -0
- data/lib/sunspot/indexer.rb +6 -0
- data/lib/sunspot/instantiated_facet.rb +7 -6
- data/lib/sunspot/instantiated_facet_row.rb +16 -1
- data/lib/sunspot/query.rb +2 -187
- data/lib/sunspot/query/boost_query.rb +20 -0
- data/lib/sunspot/query/connective.rb +98 -35
- data/lib/sunspot/query/dismax.rb +73 -0
- data/lib/sunspot/query/field_facet.rb +3 -23
- data/lib/sunspot/query/fulltext_base_query.rb +47 -0
- data/lib/sunspot/query/highlighting.rb +43 -0
- data/lib/sunspot/query/local.rb +24 -0
- data/lib/sunspot/query/pagination.rb +3 -4
- data/lib/sunspot/query/query.rb +93 -0
- data/lib/sunspot/query/query_facet.rb +15 -9
- data/lib/sunspot/query/query_facet_row.rb +3 -3
- data/lib/sunspot/query/query_field_facet.rb +20 -0
- data/lib/sunspot/query/restriction.rb +36 -15
- data/lib/sunspot/query/scope.rb +3 -159
- data/lib/sunspot/query/sort.rb +84 -15
- data/lib/sunspot/query/text_field_boost.rb +15 -0
- data/lib/sunspot/schema.rb +7 -25
- data/lib/sunspot/search.rb +63 -45
- data/lib/sunspot/search/highlight.rb +38 -0
- data/lib/sunspot/search/hit.rb +50 -3
- data/lib/sunspot/session.rb +40 -11
- data/lib/sunspot/setup.rb +47 -10
- data/lib/sunspot/text_field_setup.rb +29 -0
- data/lib/sunspot/type.rb +4 -4
- data/lib/sunspot/util.rb +27 -1
- data/solr/solr/conf/schema.xml +54 -40
- data/solr/solr/conf/solrconfig.xml +30 -0
- data/solr/solr/lib/geoapi-nogenerics-2.1-M2.jar +0 -0
- data/solr/solr/lib/gt2-referencing-2.3.1.jar +0 -0
- data/solr/solr/lib/jsr108-0.01.jar +0 -0
- data/solr/solr/lib/locallucene.jar +0 -0
- data/solr/solr/lib/localsolr.jar +0 -0
- data/spec/api/indexer/attributes_spec.rb +100 -0
- data/spec/api/indexer/batch_spec.rb +46 -0
- data/spec/api/indexer/dynamic_fields_spec.rb +33 -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 +46 -0
- data/spec/api/indexer/spec_helper.rb +1 -0
- data/spec/api/indexer_spec.rb +1 -308
- data/spec/api/query/connectives_spec.rb +162 -0
- data/spec/api/query/dsl_spec.rb +12 -0
- data/spec/api/query/dynamic_fields_spec.rb +149 -0
- data/spec/api/query/faceting_spec.rb +272 -0
- data/spec/api/query/fulltext_spec.rb +193 -0
- data/spec/api/query/highlighting_spec.rb +138 -0
- data/spec/api/query/local_spec.rb +54 -0
- data/spec/api/query/ordering_pagination_spec.rb +95 -0
- data/spec/api/query/scope_spec.rb +266 -0
- data/spec/api/query/spec_helper.rb +1 -0
- data/spec/api/query/text_field_scoping_spec.rb +30 -0
- data/spec/api/query/types_spec.rb +20 -0
- data/spec/api/search/dynamic_fields_spec.rb +27 -0
- data/spec/api/search/faceting_spec.rb +206 -0
- data/spec/api/search/highlighting_spec.rb +65 -0
- data/spec/api/search/hits_spec.rb +62 -0
- data/spec/api/search/results_spec.rb +52 -0
- data/spec/api/search/search_spec.rb +23 -0
- data/spec/api/search/spec_helper.rb +1 -0
- data/spec/api/session_spec.rb +11 -5
- data/spec/api/spec_helper.rb +1 -1
- data/spec/helpers/indexer_helper.rb +29 -0
- data/spec/helpers/query_helper.rb +13 -0
- data/spec/helpers/search_helper.rb +78 -0
- data/spec/integration/faceting_spec.rb +1 -1
- data/spec/integration/highlighting_spec.rb +22 -0
- data/spec/integration/keyword_search_spec.rb +65 -0
- data/spec/integration/local_search_spec.rb +56 -0
- data/spec/integration/scoped_search_spec.rb +15 -1
- data/spec/integration/spec_helper.rb +7 -1
- data/spec/mocks/connection.rb +24 -2
- data/spec/mocks/photo.rb +1 -1
- data/spec/mocks/post.rb +5 -3
- data/spec/mocks/super_class.rb +2 -0
- data/spec/spec_helper.rb +13 -0
- data/tasks/gemspec.rake +20 -8
- data/tasks/schema.rake +1 -1
- data/tasks/spec.rake +1 -1
- data/templates/schema.xml.erb +36 -0
- metadata +118 -52
- data/lib/sunspot/date_facet.rb +0 -36
- data/lib/sunspot/date_facet_row.rb +0 -17
- data/lib/sunspot/query/base_query.rb +0 -94
- data/lib/sunspot/query/dynamic_query.rb +0 -69
- data/lib/sunspot/query/field_query.rb +0 -57
- data/lib/sunspot/query_facet.rb +0 -33
- data/lib/sunspot/query_facet_row.rb +0 -21
- data/spec/api/build_search_spec.rb +0 -1018
- data/spec/api/query_spec.rb +0 -153
- data/spec/api/search_retrieval_spec.rb +0 -335
- data/templates/schema.xml.haml +0 -24
@@ -0,0 +1,38 @@
|
|
1
|
+
module Sunspot
|
2
|
+
class Search
|
3
|
+
#
|
4
|
+
# A Highlight represents a single highlighted fragment of text from a
|
5
|
+
# document. Depending on the highlighting parameters used for search, there
|
6
|
+
# may be more than one Highlight object for a given field in a given result.
|
7
|
+
#
|
8
|
+
class Highlight
|
9
|
+
HIGHLIGHT_MATCHER = /@@@hl@@@(.*?)@@@endhl@@@/ #:nodoc:
|
10
|
+
|
11
|
+
#
|
12
|
+
# The name of the field in which the highlight appeared.
|
13
|
+
#
|
14
|
+
attr_reader :field_name
|
15
|
+
|
16
|
+
def initialize(field_name, highlight) #:nodoc:
|
17
|
+
@field_name = field_name.to_sym
|
18
|
+
@highlight = highlight.to_s.strip
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Returns the highlighted text with formatting according to the template given in &block.
|
23
|
+
# When no block is given, <em> and </em> are used to surround the highlight.
|
24
|
+
#
|
25
|
+
# ==== Example
|
26
|
+
#
|
27
|
+
# search.highlights(:body).first.format { |word| "<strong>#{word}</strong>" }
|
28
|
+
#
|
29
|
+
def format(&block)
|
30
|
+
block ||= proc { |word| "<em>#{word}</em>" }
|
31
|
+
@highlight.gsub(HIGHLIGHT_MATCHER) do
|
32
|
+
block.call(Regexp.last_match[1])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
alias_method :formatted, :format
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/sunspot/search/hit.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
module Sunspot
|
2
2
|
class Search
|
3
|
+
#
|
4
|
+
# Hit objects represent the raw information returned by Solr for a single
|
5
|
+
# document. As well as the primary key and class name, hit objects give
|
6
|
+
# access to stored field values, keyword relevance score, and geographical
|
7
|
+
# distance (for geographical search).
|
8
|
+
#
|
3
9
|
class Hit
|
4
10
|
SPECIAL_KEYS = Set.new(%w(id type score)) #:nodoc:
|
5
11
|
|
@@ -16,15 +22,34 @@ module Sunspot
|
|
16
22
|
# is not from a keyword search.
|
17
23
|
#
|
18
24
|
attr_reader :score
|
25
|
+
#
|
26
|
+
# For geographical searches, this is the distance between the search
|
27
|
+
# centerpoint and the document's location. Otherwise, it's nil.
|
28
|
+
#
|
29
|
+
attr_reader :distance
|
19
30
|
|
20
31
|
attr_writer :instance #:nodoc:
|
21
32
|
|
22
|
-
def initialize(raw_hit, search) #:nodoc:
|
33
|
+
def initialize(raw_hit, highlights, search) #:nodoc:
|
23
34
|
@class_name, @primary_key = *raw_hit['id'].match(/([^ ]+) (.+)/)[1..2]
|
24
35
|
@score = raw_hit['score']
|
36
|
+
@distance = raw_hit['geo_distance'].to_f if raw_hit['geo_distance']
|
25
37
|
@search = search
|
26
38
|
@stored_values = raw_hit
|
27
39
|
@stored_cache = {}
|
40
|
+
@highlights = highlights
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Returns all highlights for this hit when called without parameters.
|
45
|
+
# When a field_name is provided, returns only the highlight for this field.
|
46
|
+
#
|
47
|
+
def highlights(field_name = nil)
|
48
|
+
if field_name.nil?
|
49
|
+
highlights_cache.values.flatten
|
50
|
+
else
|
51
|
+
highlights_cache[field_name.to_sym]
|
52
|
+
end
|
28
53
|
end
|
29
54
|
|
30
55
|
#
|
@@ -41,7 +66,7 @@ module Sunspot
|
|
41
66
|
def stored(field_name)
|
42
67
|
@stored_cache[field_name.to_sym] ||=
|
43
68
|
begin
|
44
|
-
field =
|
69
|
+
field = setup.field(field_name)
|
45
70
|
field.cast(@stored_values[field.indexed_name])
|
46
71
|
end
|
47
72
|
end
|
@@ -58,9 +83,31 @@ module Sunspot
|
|
58
83
|
@instance
|
59
84
|
end
|
60
85
|
|
61
|
-
def inspect
|
86
|
+
def inspect #:nodoc:
|
62
87
|
"#<Sunspot::Search::Hit:#{@class_name} #{@primary_key}>"
|
63
88
|
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def setup
|
93
|
+
@setup ||= Sunspot::Setup.for(@class_name)
|
94
|
+
end
|
95
|
+
|
96
|
+
def highlights_cache
|
97
|
+
@highlights_cache ||=
|
98
|
+
begin
|
99
|
+
cache = {}
|
100
|
+
if @highlights
|
101
|
+
@highlights.each_pair do |indexed_field_name, highlight_strings|
|
102
|
+
field_name = indexed_field_name.sub(/_[a-z]+$/, '').to_sym
|
103
|
+
cache[field_name] = highlight_strings.map do |highlight_string|
|
104
|
+
Highlight.new(field_name, highlight_string)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
cache
|
109
|
+
end
|
110
|
+
end
|
64
111
|
end
|
65
112
|
end
|
66
113
|
end
|
data/lib/sunspot/session.rb
CHANGED
@@ -15,7 +15,7 @@ module Sunspot
|
|
15
15
|
# For testing purposes
|
16
16
|
#
|
17
17
|
def connection_class #:nodoc:
|
18
|
-
@connection_class ||= RSolr
|
18
|
+
@connection_class ||= RSolr
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -29,10 +29,11 @@ module Sunspot
|
|
29
29
|
# connection. Usually you will want to stick with the default arguments
|
30
30
|
# when instantiating your own sessions.
|
31
31
|
#
|
32
|
-
def initialize(config = Configuration.build, connection = nil)
|
32
|
+
def initialize(config = Configuration.build, connection = nil, master_connection = nil)
|
33
33
|
@config = config
|
34
34
|
yield(@config) if block_given?
|
35
35
|
@connection = connection
|
36
|
+
@master_connection = master_connection
|
36
37
|
@updates = 0
|
37
38
|
end
|
38
39
|
|
@@ -41,23 +42,24 @@ module Sunspot
|
|
41
42
|
#
|
42
43
|
def new_search(*types)
|
43
44
|
types.flatten!
|
45
|
+
if types.empty?
|
46
|
+
raise(ArgumentError, "You must specify at least one type to search")
|
47
|
+
end
|
44
48
|
setup =
|
45
49
|
if types.length == 1
|
46
50
|
Setup.for(types.first)
|
47
51
|
else
|
48
52
|
CompositeSetup.for(types)
|
49
53
|
end
|
50
|
-
Search.new(connection, setup, Query::Query.new(types,
|
54
|
+
Search.new(connection, setup, Query::Query.new(types), @config)
|
51
55
|
end
|
52
56
|
|
53
57
|
#
|
54
58
|
# See Sunspot.search
|
55
59
|
#
|
56
60
|
def search(*types, &block)
|
57
|
-
options = types.last.is_a?(Hash) ? types.pop : {}
|
58
61
|
search = new_search(*types)
|
59
62
|
search.build(&block) if block
|
60
|
-
search.query.options = options
|
61
63
|
search.execute!
|
62
64
|
end
|
63
65
|
|
@@ -83,7 +85,7 @@ module Sunspot
|
|
83
85
|
#
|
84
86
|
def commit
|
85
87
|
@updates = 0
|
86
|
-
|
88
|
+
master_connection.commit
|
87
89
|
end
|
88
90
|
|
89
91
|
#
|
@@ -133,7 +135,7 @@ module Sunspot
|
|
133
135
|
classes.flatten!
|
134
136
|
if classes.empty?
|
135
137
|
@updates += 1
|
136
|
-
Indexer.remove_all(
|
138
|
+
Indexer.remove_all(master_connection)
|
137
139
|
else
|
138
140
|
@updates += classes.length
|
139
141
|
for clazz in classes
|
@@ -186,16 +188,43 @@ module Sunspot
|
|
186
188
|
def connection
|
187
189
|
@connection ||=
|
188
190
|
begin
|
189
|
-
connection = self.class.connection_class.
|
190
|
-
|
191
|
+
connection = self.class.connection_class.connect(
|
192
|
+
:url => config.solr.url,
|
193
|
+
:adapter => config.http_client
|
191
194
|
)
|
192
|
-
connection.adapter
|
195
|
+
connection.message.adapter =
|
196
|
+
RSolr::Message::Adapter.const_get(
|
197
|
+
Util.camel_case(config.xml_builder.to_s)
|
198
|
+
).new
|
193
199
|
connection
|
194
200
|
end
|
195
201
|
end
|
196
202
|
|
203
|
+
#
|
204
|
+
# Retrieve the Solr connection to the master for this session, creating one
|
205
|
+
# if it does not already exist.
|
206
|
+
#
|
207
|
+
# ==== Returns
|
208
|
+
#
|
209
|
+
# Solr::Connection:: The connection for this session
|
210
|
+
#
|
211
|
+
def master_connection
|
212
|
+
@master_connection ||=
|
213
|
+
begin
|
214
|
+
if config.master_solr.url && config.master_solr.url != config.solr.url
|
215
|
+
master_connection = self.class.connection_class.new(
|
216
|
+
RSolr::Adapter::HTTP.new(:url => config.master_solr.url)
|
217
|
+
)
|
218
|
+
master_connection.adapter.connector.adapter_name = config.http_client
|
219
|
+
master_connection
|
220
|
+
else
|
221
|
+
connection
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
197
226
|
def indexer
|
198
|
-
@indexer ||= Indexer.new(
|
227
|
+
@indexer ||= Indexer.new(master_connection)
|
199
228
|
end
|
200
229
|
end
|
201
230
|
end
|
data/lib/sunspot/setup.rb
CHANGED
@@ -57,6 +57,20 @@ module Sunspot
|
|
57
57
|
@dynamic_field_factories_cache[field_factory.name] = field_factory
|
58
58
|
end
|
59
59
|
|
60
|
+
#
|
61
|
+
# The coordinates field factory is used for populating the coordinate fields
|
62
|
+
# of documents during index, but does not actually generate fields (since
|
63
|
+
# the field names used in search are static).
|
64
|
+
#
|
65
|
+
def set_coordinates_field(name)
|
66
|
+
@coordinates_field_factory = FieldFactory::Coordinates.new(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Add a document boost to documents at index time. Document boost can be
|
71
|
+
# static (the same for all documents of this class), or extracted on a per-
|
72
|
+
# document basis using either attribute or block extraction as per usual.
|
73
|
+
#
|
60
74
|
def add_document_boost(attr_name, &block)
|
61
75
|
@document_boost_extractor =
|
62
76
|
if attr_name
|
@@ -77,6 +91,9 @@ module Sunspot
|
|
77
91
|
@dsl.instance_eval(&block)
|
78
92
|
end
|
79
93
|
|
94
|
+
#
|
95
|
+
# Return the Field with the given (public-facing) name
|
96
|
+
#
|
80
97
|
def field(field_name)
|
81
98
|
if field_factory = @field_factories_cache[field_name.to_sym]
|
82
99
|
field_factory.build
|
@@ -88,17 +105,27 @@ module Sunspot
|
|
88
105
|
end
|
89
106
|
end
|
90
107
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
108
|
+
#
|
109
|
+
# Return one or more text fields with the given public-facing name. This
|
110
|
+
# implementation will always return a single field (in an array), but
|
111
|
+
# CompositeSetup objects might return more than one.
|
112
|
+
#
|
113
|
+
def text_fields(field_name)
|
114
|
+
text_field =
|
115
|
+
if field_factory = @text_field_factories_cache[field_name.to_sym]
|
116
|
+
field_factory.build
|
117
|
+
else
|
118
|
+
raise(
|
119
|
+
UnrecognizedFieldError,
|
120
|
+
"No text field configured for #{@clazz.name} with name '#{field_name}'"
|
121
|
+
)
|
122
|
+
end
|
123
|
+
[text_field]
|
100
124
|
end
|
101
125
|
|
126
|
+
#
|
127
|
+
# Return the DynamicFieldFactory with the given base name
|
128
|
+
#
|
102
129
|
def dynamic_field_factory(field_name)
|
103
130
|
@dynamic_field_factories_cache[field_name.to_sym] || raise(
|
104
131
|
UnrecognizedFieldError,
|
@@ -106,11 +133,17 @@ module Sunspot
|
|
106
133
|
)
|
107
134
|
end
|
108
135
|
|
136
|
+
#
|
137
|
+
# Return all attribute fields
|
138
|
+
#
|
109
139
|
def fields
|
110
140
|
field_factories.map { |field_factory| field_factory.build }
|
111
141
|
end
|
112
142
|
|
113
|
-
|
143
|
+
#
|
144
|
+
# Return all text fields
|
145
|
+
#
|
146
|
+
def all_text_fields
|
114
147
|
text_field_factories.map { |text_field_factory| text_field_factory.build }
|
115
148
|
end
|
116
149
|
|
@@ -148,6 +181,7 @@ module Sunspot
|
|
148
181
|
def all_field_factories
|
149
182
|
all_field_factories = []
|
150
183
|
all_field_factories.concat(field_factories).concat(text_field_factories).concat(dynamic_field_factories)
|
184
|
+
all_field_factories << @coordinates_field_factory if @coordinates_field_factory
|
151
185
|
all_field_factories
|
152
186
|
end
|
153
187
|
|
@@ -173,6 +207,9 @@ module Sunspot
|
|
173
207
|
Util.full_const_get(@class_name)
|
174
208
|
end
|
175
209
|
|
210
|
+
#
|
211
|
+
# Get the document boost for a given model
|
212
|
+
#
|
176
213
|
def document_boost_for(model)
|
177
214
|
if @document_boost_extractor
|
178
215
|
@document_boost_extractor.value_for(model)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Sunspot
|
2
|
+
#
|
3
|
+
# A TextFieldSetup encapsulates a regular (or composite) setup, and exposes
|
4
|
+
# the #field() method returning text fields instead of attribute fields.
|
5
|
+
#
|
6
|
+
class TextFieldSetup #:nodoc:
|
7
|
+
def initialize(setup)
|
8
|
+
@setup = setup
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# Return a text field with the given name. Duck-type compatible with
|
13
|
+
# Setup and CompositeSetup, but return text fields instead.
|
14
|
+
#
|
15
|
+
def field(name)
|
16
|
+
fields = @setup.text_fields(name)
|
17
|
+
if fields
|
18
|
+
if fields.length == 1
|
19
|
+
fields.first
|
20
|
+
else
|
21
|
+
raise(
|
22
|
+
Sunspot::UnrecognizedFieldError,
|
23
|
+
"The text field with name #{name} has incompatible configurations for the classes #{@setup.type_names.join(', ')}"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/sunspot/type.rb
CHANGED
@@ -147,7 +147,7 @@ module Sunspot
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
|
-
def cast(string)
|
150
|
+
def cast(string) #:nodoc:
|
151
151
|
time = Time.xmlschema(string)
|
152
152
|
Date.civil(time.year, time.mon, time.mday)
|
153
153
|
end
|
@@ -183,15 +183,15 @@ module Sunspot
|
|
183
183
|
|
184
184
|
module ClassType
|
185
185
|
class <<self
|
186
|
-
def indexed_name(name)
|
186
|
+
def indexed_name(name) #:nodoc:
|
187
187
|
'class_name'
|
188
188
|
end
|
189
189
|
|
190
|
-
def to_indexed(value)
|
190
|
+
def to_indexed(value) #:nodoc:
|
191
191
|
value.name
|
192
192
|
end
|
193
193
|
|
194
|
-
def cast(string)
|
194
|
+
def cast(string) #:nodoc:
|
195
195
|
Sunspot::Util.full_const_get(string)
|
196
196
|
end
|
197
197
|
end
|
data/lib/sunspot/util.rb
CHANGED
@@ -66,7 +66,7 @@ module Sunspot
|
|
66
66
|
#
|
67
67
|
def full_const_get(string)
|
68
68
|
string.split('::').inject(Object) do |context, const_name|
|
69
|
-
context.const_get(const_name)
|
69
|
+
context.const_defined?(const_name) ? context.const_get(const_name) : context.const_missing(const_name)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -160,5 +160,31 @@ module Sunspot
|
|
160
160
|
destination
|
161
161
|
end
|
162
162
|
end
|
163
|
+
|
164
|
+
class Coordinates #:nodoc:
|
165
|
+
def initialize(coords)
|
166
|
+
@coords = coords
|
167
|
+
end
|
168
|
+
|
169
|
+
def lat
|
170
|
+
if @coords.respond_to?(:[])
|
171
|
+
@coords[0]
|
172
|
+
else
|
173
|
+
@coords.lat
|
174
|
+
end.to_f
|
175
|
+
end
|
176
|
+
|
177
|
+
def lng
|
178
|
+
if @coords.respond_to?(:[])
|
179
|
+
@coords[1]
|
180
|
+
elsif @coords.respond_to?(:lng)
|
181
|
+
@coords.lng
|
182
|
+
elsif @coords.respond_to?(:lon)
|
183
|
+
@coords.lon
|
184
|
+
elsif @coords.respond_to?(:long)
|
185
|
+
@coords.long
|
186
|
+
end.to_f
|
187
|
+
end
|
188
|
+
end
|
163
189
|
end
|
164
190
|
end
|
data/solr/solr/conf/schema.xml
CHANGED
@@ -1,50 +1,64 @@
|
|
1
|
-
<?xml version=
|
2
|
-
<schema
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<schema version="0.9" name="sunspot">
|
3
3
|
<types>
|
4
|
-
<fieldtype class=
|
4
|
+
<fieldtype class="solr.TextField" positionIncrementGap="100" name="text">
|
5
5
|
<analyzer>
|
6
|
-
<tokenizer class=
|
7
|
-
<filter class=
|
8
|
-
<filter class=
|
6
|
+
<tokenizer class="solr.StandardTokenizerFactory"/>
|
7
|
+
<filter class="solr.StandardFilterFactory"/>
|
8
|
+
<filter class="solr.LowerCaseFilterFactory"/>
|
9
9
|
</analyzer>
|
10
10
|
</fieldtype>
|
11
|
-
<fieldtype class=
|
12
|
-
<fieldtype class=
|
13
|
-
<fieldtype class=
|
14
|
-
<fieldtype class=
|
15
|
-
<fieldtype class=
|
16
|
-
<fieldtype class=
|
11
|
+
<fieldtype class="solr.RandomSortField" name="rand"/>
|
12
|
+
<fieldtype name="boolean" class="solr.BoolField" omitNorms="true"/>
|
13
|
+
<fieldtype name="sfloat" class="solr.SortableFloatField" omitNorms="true"/>
|
14
|
+
<fieldtype name="date" class="solr.DateField" omitNorms="true"/>
|
15
|
+
<fieldtype name="sint" class="solr.SortableIntField" omitNorms="true"/>
|
16
|
+
<fieldtype name="string" class="solr.StrField" omitNorms="true"/>
|
17
|
+
<fieldtype name="sdouble" class="solr.SortableDoubleField" omitNorms="true"/>
|
18
|
+
<fieldtype name="slong" class="solr.SortableLongField" omitNorms="true"/>
|
17
19
|
</types>
|
18
20
|
<fields>
|
19
|
-
<field indexed=
|
20
|
-
<field indexed=
|
21
|
-
<field
|
22
|
-
<field indexed=
|
23
|
-
<
|
24
|
-
<
|
25
|
-
<dynamicField indexed=
|
26
|
-
<dynamicField indexed=
|
27
|
-
<dynamicField
|
28
|
-
<dynamicField
|
29
|
-
<dynamicField
|
30
|
-
<dynamicField
|
31
|
-
<dynamicField
|
32
|
-
<dynamicField
|
33
|
-
<dynamicField
|
34
|
-
<dynamicField
|
35
|
-
<dynamicField
|
36
|
-
<dynamicField
|
37
|
-
<dynamicField
|
38
|
-
<dynamicField
|
39
|
-
<dynamicField
|
40
|
-
<dynamicField
|
41
|
-
<dynamicField
|
42
|
-
<dynamicField
|
43
|
-
<dynamicField
|
44
|
-
<dynamicField
|
21
|
+
<field name="id" type="string" indexed="true" stored="true" multiValued="false" />
|
22
|
+
<field name="type" type="string" indexed="true" stored="false" multiValued="true" />
|
23
|
+
<field name="class_name" type="string" indexed="true" stored="false" multiValued="false" />
|
24
|
+
<field name="text" type="text" indexed="true" stored="false" multiValued="true" />
|
25
|
+
<field name="lat" type="sdouble" indexed="true" stored="true" multiValued="false" />
|
26
|
+
<field name="long" type="sdouble" indexed="true" stored="true" multiValued="false" />
|
27
|
+
<dynamicField name="*_text" type="text" indexed="true" stored="false" multiValued="true" />
|
28
|
+
<dynamicField name="*_texts" type="text" indexed="true" stored="true" multiValued="true" />
|
29
|
+
<dynamicField name="random_*" type="rand" indexed="true" stored="false" multiValued="false" />
|
30
|
+
<dynamicField name="_local*" type="sdouble" indexed="true" stored="false" multiValued="false" />
|
31
|
+
<dynamicField name="*_b" type="boolean" indexed="true" stored="false" multiValued="false" />
|
32
|
+
<dynamicField name="*_f" type="sfloat" indexed="true" stored="false" multiValued="false" />
|
33
|
+
<dynamicField name="*_d" type="date" indexed="true" stored="false" multiValued="false" />
|
34
|
+
<dynamicField name="*_i" type="sint" indexed="true" stored="false" multiValued="false" />
|
35
|
+
<dynamicField name="*_s" type="string" indexed="true" stored="false" multiValued="false" />
|
36
|
+
<dynamicField name="*_e" type="sdouble" indexed="true" stored="false" multiValued="false" />
|
37
|
+
<dynamicField name="*_l" type="slong" indexed="true" stored="false" multiValued="false" />
|
38
|
+
<dynamicField name="*_bm" type="boolean" indexed="true" stored="false" multiValued="true" />
|
39
|
+
<dynamicField name="*_fm" type="sfloat" indexed="true" stored="false" multiValued="true" />
|
40
|
+
<dynamicField name="*_dm" type="date" indexed="true" stored="false" multiValued="true" />
|
41
|
+
<dynamicField name="*_im" type="sint" indexed="true" stored="false" multiValued="true" />
|
42
|
+
<dynamicField name="*_sm" type="string" indexed="true" stored="false" multiValued="true" />
|
43
|
+
<dynamicField name="*_em" type="sdouble" indexed="true" stored="false" multiValued="true" />
|
44
|
+
<dynamicField name="*_lm" type="slong" indexed="true" stored="false" multiValued="true" />
|
45
|
+
<dynamicField name="*_bs" type="boolean" indexed="true" stored="true" multiValued="false" />
|
46
|
+
<dynamicField name="*_fs" type="sfloat" indexed="true" stored="true" multiValued="false" />
|
47
|
+
<dynamicField name="*_ds" type="date" indexed="true" stored="true" multiValued="false" />
|
48
|
+
<dynamicField name="*_is" type="sint" indexed="true" stored="true" multiValued="false" />
|
49
|
+
<dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="false" />
|
50
|
+
<dynamicField name="*_es" type="sdouble" indexed="true" stored="true" multiValued="false" />
|
51
|
+
<dynamicField name="*_ls" type="slong" indexed="true" stored="true" multiValued="false" />
|
52
|
+
<dynamicField name="*_bms" type="boolean" indexed="true" stored="true" multiValued="true" />
|
53
|
+
<dynamicField name="*_fms" type="sfloat" indexed="true" stored="true" multiValued="true" />
|
54
|
+
<dynamicField name="*_dms" type="date" indexed="true" stored="true" multiValued="true" />
|
55
|
+
<dynamicField name="*_ims" type="sint" indexed="true" stored="true" multiValued="true" />
|
56
|
+
<dynamicField name="*_sms" type="string" indexed="true" stored="true" multiValued="true" />
|
57
|
+
<dynamicField name="*_ems" type="sdouble" indexed="true" stored="true" multiValued="true" />
|
58
|
+
<dynamicField name="*_lms" type="slong" indexed="true" stored="true" multiValued="true" />
|
45
59
|
</fields>
|
46
60
|
<uniqueKey>id</uniqueKey>
|
47
61
|
<defaultSearchField>text</defaultSearchField>
|
48
|
-
<solrQueryParser defaultOperator=
|
49
|
-
<copyField dest=
|
62
|
+
<solrQueryParser defaultOperator="AND"/>
|
63
|
+
<copyField dest="text" source="*_text"/>
|
50
64
|
</schema>
|