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.
Files changed (120) hide show
  1. data/History.txt +38 -0
  2. data/README.rdoc +40 -3
  3. data/TODO +10 -8
  4. data/VERSION.yml +2 -2
  5. data/bin/sunspot-configure-solr +22 -28
  6. data/bin/sunspot-solr +50 -29
  7. data/lib/sunspot.rb +8 -18
  8. data/lib/sunspot/adapters.rb +1 -1
  9. data/lib/sunspot/composite_setup.rb +13 -15
  10. data/lib/sunspot/configuration.rb +21 -0
  11. data/lib/sunspot/data_extractor.rb +3 -0
  12. data/lib/sunspot/dsl.rb +2 -1
  13. data/lib/sunspot/dsl/field_query.rb +33 -6
  14. data/lib/sunspot/dsl/fields.rb +14 -1
  15. data/lib/sunspot/dsl/fulltext.rb +168 -0
  16. data/lib/sunspot/dsl/query.rb +82 -5
  17. data/lib/sunspot/dsl/query_facet.rb +3 -3
  18. data/lib/sunspot/dsl/restriction.rb +7 -7
  19. data/lib/sunspot/dsl/scope.rb +17 -10
  20. data/lib/sunspot/dsl/search.rb +2 -2
  21. data/lib/sunspot/facet.rb +12 -39
  22. data/lib/sunspot/facet_data.rb +169 -0
  23. data/lib/sunspot/facet_row.rb +5 -27
  24. data/lib/sunspot/field.rb +50 -26
  25. data/lib/sunspot/field_factory.rb +15 -0
  26. data/lib/sunspot/indexer.rb +6 -0
  27. data/lib/sunspot/instantiated_facet.rb +7 -6
  28. data/lib/sunspot/instantiated_facet_row.rb +16 -1
  29. data/lib/sunspot/query.rb +2 -187
  30. data/lib/sunspot/query/boost_query.rb +20 -0
  31. data/lib/sunspot/query/connective.rb +98 -35
  32. data/lib/sunspot/query/dismax.rb +73 -0
  33. data/lib/sunspot/query/field_facet.rb +3 -23
  34. data/lib/sunspot/query/fulltext_base_query.rb +47 -0
  35. data/lib/sunspot/query/highlighting.rb +43 -0
  36. data/lib/sunspot/query/local.rb +24 -0
  37. data/lib/sunspot/query/pagination.rb +3 -4
  38. data/lib/sunspot/query/query.rb +93 -0
  39. data/lib/sunspot/query/query_facet.rb +15 -9
  40. data/lib/sunspot/query/query_facet_row.rb +3 -3
  41. data/lib/sunspot/query/query_field_facet.rb +20 -0
  42. data/lib/sunspot/query/restriction.rb +36 -15
  43. data/lib/sunspot/query/scope.rb +3 -159
  44. data/lib/sunspot/query/sort.rb +84 -15
  45. data/lib/sunspot/query/text_field_boost.rb +15 -0
  46. data/lib/sunspot/schema.rb +7 -25
  47. data/lib/sunspot/search.rb +63 -45
  48. data/lib/sunspot/search/highlight.rb +38 -0
  49. data/lib/sunspot/search/hit.rb +50 -3
  50. data/lib/sunspot/session.rb +40 -11
  51. data/lib/sunspot/setup.rb +47 -10
  52. data/lib/sunspot/text_field_setup.rb +29 -0
  53. data/lib/sunspot/type.rb +4 -4
  54. data/lib/sunspot/util.rb +27 -1
  55. data/solr/solr/conf/schema.xml +54 -40
  56. data/solr/solr/conf/solrconfig.xml +30 -0
  57. data/solr/solr/lib/geoapi-nogenerics-2.1-M2.jar +0 -0
  58. data/solr/solr/lib/gt2-referencing-2.3.1.jar +0 -0
  59. data/solr/solr/lib/jsr108-0.01.jar +0 -0
  60. data/solr/solr/lib/locallucene.jar +0 -0
  61. data/solr/solr/lib/localsolr.jar +0 -0
  62. data/spec/api/indexer/attributes_spec.rb +100 -0
  63. data/spec/api/indexer/batch_spec.rb +46 -0
  64. data/spec/api/indexer/dynamic_fields_spec.rb +33 -0
  65. data/spec/api/indexer/fixed_fields_spec.rb +57 -0
  66. data/spec/api/indexer/fulltext_spec.rb +43 -0
  67. data/spec/api/indexer/removal_spec.rb +46 -0
  68. data/spec/api/indexer/spec_helper.rb +1 -0
  69. data/spec/api/indexer_spec.rb +1 -308
  70. data/spec/api/query/connectives_spec.rb +162 -0
  71. data/spec/api/query/dsl_spec.rb +12 -0
  72. data/spec/api/query/dynamic_fields_spec.rb +149 -0
  73. data/spec/api/query/faceting_spec.rb +272 -0
  74. data/spec/api/query/fulltext_spec.rb +193 -0
  75. data/spec/api/query/highlighting_spec.rb +138 -0
  76. data/spec/api/query/local_spec.rb +54 -0
  77. data/spec/api/query/ordering_pagination_spec.rb +95 -0
  78. data/spec/api/query/scope_spec.rb +266 -0
  79. data/spec/api/query/spec_helper.rb +1 -0
  80. data/spec/api/query/text_field_scoping_spec.rb +30 -0
  81. data/spec/api/query/types_spec.rb +20 -0
  82. data/spec/api/search/dynamic_fields_spec.rb +27 -0
  83. data/spec/api/search/faceting_spec.rb +206 -0
  84. data/spec/api/search/highlighting_spec.rb +65 -0
  85. data/spec/api/search/hits_spec.rb +62 -0
  86. data/spec/api/search/results_spec.rb +52 -0
  87. data/spec/api/search/search_spec.rb +23 -0
  88. data/spec/api/search/spec_helper.rb +1 -0
  89. data/spec/api/session_spec.rb +11 -5
  90. data/spec/api/spec_helper.rb +1 -1
  91. data/spec/helpers/indexer_helper.rb +29 -0
  92. data/spec/helpers/query_helper.rb +13 -0
  93. data/spec/helpers/search_helper.rb +78 -0
  94. data/spec/integration/faceting_spec.rb +1 -1
  95. data/spec/integration/highlighting_spec.rb +22 -0
  96. data/spec/integration/keyword_search_spec.rb +65 -0
  97. data/spec/integration/local_search_spec.rb +56 -0
  98. data/spec/integration/scoped_search_spec.rb +15 -1
  99. data/spec/integration/spec_helper.rb +7 -1
  100. data/spec/mocks/connection.rb +24 -2
  101. data/spec/mocks/photo.rb +1 -1
  102. data/spec/mocks/post.rb +5 -3
  103. data/spec/mocks/super_class.rb +2 -0
  104. data/spec/spec_helper.rb +13 -0
  105. data/tasks/gemspec.rake +20 -8
  106. data/tasks/schema.rake +1 -1
  107. data/tasks/spec.rake +1 -1
  108. data/templates/schema.xml.erb +36 -0
  109. metadata +118 -52
  110. data/lib/sunspot/date_facet.rb +0 -36
  111. data/lib/sunspot/date_facet_row.rb +0 -17
  112. data/lib/sunspot/query/base_query.rb +0 -94
  113. data/lib/sunspot/query/dynamic_query.rb +0 -69
  114. data/lib/sunspot/query/field_query.rb +0 -57
  115. data/lib/sunspot/query_facet.rb +0 -33
  116. data/lib/sunspot/query_facet_row.rb +0 -21
  117. data/spec/api/build_search_spec.rb +0 -1018
  118. data/spec/api/query_spec.rb +0 -153
  119. data/spec/api/search_retrieval_spec.rb +0 -335
  120. 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
@@ -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 = Sunspot::Setup.for(@class_name).field(field_name)
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
@@ -15,7 +15,7 @@ module Sunspot
15
15
  # For testing purposes
16
16
  #
17
17
  def connection_class #:nodoc:
18
- @connection_class ||= RSolr::Connection
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, setup, @config))
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
- connection.commit
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(connection)
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.new(
190
- RSolr::Adapter::HTTP.new(:url => config.solr.url)
191
+ connection = self.class.connection_class.connect(
192
+ :url => config.solr.url,
193
+ :adapter => config.http_client
191
194
  )
192
- connection.adapter.connector.adapter_name = config.http_client
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(connection)
227
+ @indexer ||= Indexer.new(master_connection)
199
228
  end
200
229
  end
201
230
  end
@@ -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
- def text_field(field_name)
92
- if field_factory = @text_field_factories_cache[field_name.to_sym]
93
- field_factory.build
94
- else
95
- raise(
96
- UnrecognizedFieldError,
97
- "No text field configured for #{@clazz.name} with name '#{field_name}'"
98
- )
99
- end
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
- def text_fields
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
@@ -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
@@ -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
@@ -1,50 +1,64 @@
1
- <?xml version='1.0' encoding='utf-8' ?>
2
- <schema name='sunspot' version='0.9'>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <schema version="0.9" name="sunspot">
3
3
  <types>
4
- <fieldtype class='solr.TextField' name='text' positionIncrementGap='100'>
4
+ <fieldtype class="solr.TextField" positionIncrementGap="100" name="text">
5
5
  <analyzer>
6
- <tokenizer class='solr.StandardTokenizerFactory' />
7
- <filter class='solr.StandardFilterFactory' />
8
- <filter class='solr.LowerCaseFilterFactory' />
6
+ <tokenizer class="solr.StandardTokenizerFactory"/>
7
+ <filter class="solr.StandardFilterFactory"/>
8
+ <filter class="solr.LowerCaseFilterFactory"/>
9
9
  </analyzer>
10
10
  </fieldtype>
11
- <fieldtype class='solr.RandomSortField' name='rand'></fieldtype>
12
- <fieldtype class='solr.BoolField' name='boolean' omitNorms='true' />
13
- <fieldtype class='solr.SortableFloatField' name='sfloat' omitNorms='true' />
14
- <fieldtype class='solr.DateField' name='date' omitNorms='true' />
15
- <fieldtype class='solr.SortableIntField' name='sint' omitNorms='true' />
16
- <fieldtype class='solr.StrField' name='string' omitNorms='true' />
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='true' multiValued='false' name='id' stored='true' type='string' />
20
- <field indexed='true' multiValued='true' name='type' stored='false' type='string' />
21
- <field indexed='true' multiValued='false' name='class_name' stored='false' type='string' />
22
- <field indexed='true' multiValued='true' name='text' stored='false' type='text' />
23
- <dynamicField indexed='true' multiValued='true' name='*_text' stored='false' type='text' />
24
- <dynamicField indexed='true' name='random_*' stored='false' type='rand' />
25
- <dynamicField indexed='true' multiValued='false' name='*_b' stored='false' type='boolean' />
26
- <dynamicField indexed='true' multiValued='false' name='*_f' stored='false' type='sfloat' />
27
- <dynamicField indexed='true' multiValued='false' name='*_d' stored='false' type='date' />
28
- <dynamicField indexed='true' multiValued='false' name='*_i' stored='false' type='sint' />
29
- <dynamicField indexed='true' multiValued='false' name='*_s' stored='false' type='string' />
30
- <dynamicField indexed='true' multiValued='true' name='*_bm' stored='false' type='boolean' />
31
- <dynamicField indexed='true' multiValued='true' name='*_fm' stored='false' type='sfloat' />
32
- <dynamicField indexed='true' multiValued='true' name='*_dm' stored='false' type='date' />
33
- <dynamicField indexed='true' multiValued='true' name='*_im' stored='false' type='sint' />
34
- <dynamicField indexed='true' multiValued='true' name='*_sm' stored='false' type='string' />
35
- <dynamicField indexed='true' multiValued='false' name='*_bs' stored='true' type='boolean' />
36
- <dynamicField indexed='true' multiValued='false' name='*_fs' stored='true' type='sfloat' />
37
- <dynamicField indexed='true' multiValued='false' name='*_ds' stored='true' type='date' />
38
- <dynamicField indexed='true' multiValued='false' name='*_is' stored='true' type='sint' />
39
- <dynamicField indexed='true' multiValued='false' name='*_ss' stored='true' type='string' />
40
- <dynamicField indexed='true' multiValued='true' name='*_bms' stored='true' type='boolean' />
41
- <dynamicField indexed='true' multiValued='true' name='*_fms' stored='true' type='sfloat' />
42
- <dynamicField indexed='true' multiValued='true' name='*_dms' stored='true' type='date' />
43
- <dynamicField indexed='true' multiValued='true' name='*_ims' stored='true' type='sint' />
44
- <dynamicField indexed='true' multiValued='true' name='*_sms' stored='true' type='string' />
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='AND' />
49
- <copyField dest='text' source='*_text' />
62
+ <solrQueryParser defaultOperator="AND"/>
63
+ <copyField dest="text" source="*_text"/>
50
64
  </schema>