sunspot 0.9.8 → 0.10.0

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 (115) hide show
  1. data/History.txt +32 -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/adapters.rb +1 -1
  8. data/lib/sunspot/composite_setup.rb +13 -15
  9. data/lib/sunspot/configuration.rb +14 -0
  10. data/lib/sunspot/data_extractor.rb +3 -0
  11. data/lib/sunspot/dsl/field_query.rb +33 -6
  12. data/lib/sunspot/dsl/fields.rb +14 -1
  13. data/lib/sunspot/dsl/fulltext.rb +168 -0
  14. data/lib/sunspot/dsl/query.rb +82 -5
  15. data/lib/sunspot/dsl/query_facet.rb +3 -3
  16. data/lib/sunspot/dsl/restriction.rb +7 -7
  17. data/lib/sunspot/dsl/scope.rb +17 -10
  18. data/lib/sunspot/dsl/search.rb +2 -2
  19. data/lib/sunspot/dsl.rb +2 -1
  20. data/lib/sunspot/facet.rb +9 -1
  21. data/lib/sunspot/facet_data.rb +56 -7
  22. data/lib/sunspot/facet_row.rb +2 -0
  23. data/lib/sunspot/field.rb +50 -26
  24. data/lib/sunspot/field_factory.rb +15 -0
  25. data/lib/sunspot/indexer.rb +6 -0
  26. data/lib/sunspot/instantiated_facet.rb +6 -9
  27. data/lib/sunspot/instantiated_facet_row.rb +7 -2
  28. data/lib/sunspot/query/boost_query.rb +20 -0
  29. data/lib/sunspot/query/connective.rb +98 -35
  30. data/lib/sunspot/query/dismax.rb +69 -0
  31. data/lib/sunspot/query/field_facet.rb +1 -22
  32. data/lib/sunspot/query/fulltext_base_query.rb +47 -0
  33. data/lib/sunspot/query/highlighting.rb +43 -0
  34. data/lib/sunspot/query/local.rb +24 -0
  35. data/lib/sunspot/query/pagination.rb +3 -4
  36. data/lib/sunspot/query/query.rb +93 -0
  37. data/lib/sunspot/query/query_facet.rb +14 -9
  38. data/lib/sunspot/query/query_facet_row.rb +3 -3
  39. data/lib/sunspot/query/query_field_facet.rb +10 -3
  40. data/lib/sunspot/query/restriction.rb +36 -15
  41. data/lib/sunspot/query/scope.rb +3 -159
  42. data/lib/sunspot/query/sort.rb +84 -15
  43. data/lib/sunspot/query/text_field_boost.rb +15 -0
  44. data/lib/sunspot/query.rb +2 -188
  45. data/lib/sunspot/schema.rb +7 -25
  46. data/lib/sunspot/search/highlight.rb +38 -0
  47. data/lib/sunspot/search/hit.rb +50 -3
  48. data/lib/sunspot/search.rb +51 -32
  49. data/lib/sunspot/session.rb +32 -12
  50. data/lib/sunspot/setup.rb +47 -10
  51. data/lib/sunspot/text_field_setup.rb +29 -0
  52. data/lib/sunspot/type.rb +4 -4
  53. data/lib/sunspot/util.rb +27 -1
  54. data/lib/sunspot.rb +8 -17
  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/spec_helper.rb +1 -1
  90. data/spec/helpers/indexer_helper.rb +29 -0
  91. data/spec/helpers/query_helper.rb +13 -0
  92. data/spec/helpers/search_helper.rb +78 -0
  93. data/spec/integration/faceting_spec.rb +1 -1
  94. data/spec/integration/highlighting_spec.rb +22 -0
  95. data/spec/integration/keyword_search_spec.rb +65 -0
  96. data/spec/integration/local_search_spec.rb +56 -0
  97. data/spec/integration/scoped_search_spec.rb +15 -1
  98. data/spec/integration/spec_helper.rb +3 -3
  99. data/spec/mocks/connection.rb +14 -1
  100. data/spec/mocks/photo.rb +1 -1
  101. data/spec/mocks/post.rb +5 -3
  102. data/spec/mocks/super_class.rb +2 -0
  103. data/spec/spec_helper.rb +13 -0
  104. data/tasks/gemspec.rake +18 -7
  105. data/tasks/schema.rake +1 -1
  106. data/tasks/spec.rake +1 -1
  107. data/templates/schema.xml.erb +36 -0
  108. metadata +117 -48
  109. data/lib/sunspot/query/base_query.rb +0 -90
  110. data/lib/sunspot/query/dynamic_query.rb +0 -69
  111. data/lib/sunspot/query/field_query.rb +0 -63
  112. data/spec/api/build_search_spec.rb +0 -1017
  113. data/spec/api/query_spec.rb +0 -153
  114. data/spec/api/search_retrieval_spec.rb +0 -362
  115. data/templates/schema.xml.haml +0 -24
data/History.txt CHANGED
@@ -1,3 +1,35 @@
1
+ == 0.10.0 2009-10-08
2
+ * Support for geographical search using LocalSolr
3
+ * Support for keyword highlighting, with custom deferred formatting
4
+ * New fulltext DSL for specifying advanced dismax options
5
+ * Support boost queries
6
+ * Support for search-time field boost
7
+ * Support for phrase fields
8
+ * Support for prefix queries
9
+ * Set default search-time field boost in setup
10
+ * Restrict field facet to a set of desired values
11
+ * Query facets support all facet options
12
+ * Allow scoping by text fields
13
+ * Support executing searches repeatedly
14
+ * Allow setting of Solr URL for integration tests in environment variable
15
+ * Add support for master/slave configurations
16
+ * Added logging options to sunspot-solr executable
17
+ * Added default solr config file location to Sunspot::Configuration
18
+ * Informative, non-firehose Search#inspect
19
+ * No longer require arguments to #paginate
20
+ * Silently ignore keyword calls with nil/blank/whitespace keywords
21
+ * Don't require that all searched types have a referenced field
22
+ * Correct backwards ranges
23
+ * Raise descriptive error if no types passed to search
24
+ * Handle empty query facets, query facet rows, and connectives
25
+ * Quote values in range restrictions if they contain spaces
26
+ * Fix bug in Sunspot::Util.full_const_get
27
+ * Remove support for :other option in time faceting
28
+ * Remove order_by_random() method
29
+ * Removed options and Query from public API
30
+ * Use built-in optparse instead of optiflag in bin/sunspot-solr
31
+ * Remove dependency on haml and use erb since it is only used to generate one file
32
+
1
33
  == 0.9.0 2009-07-21
2
34
  * Use Dismax parser for keyword search
3
35
  * Field and document boosting
data/README.rdoc CHANGED
@@ -10,6 +10,11 @@ features for indexing objects and searching for them.
10
10
  Sunspot is designed to be easily plugged in to any ORM, or even non-database-backed
11
11
  objects such as the filesystem.
12
12
 
13
+ This README is intended as a quick primer on what Sunspot is capable of; for
14
+ detailed treatment of Sunspot's full feature range, check out the wiki:
15
+ http://wiki.github.com/outoftime/sunspot
16
+
17
+
13
18
  === Features:
14
19
 
15
20
  * Define indexing strategy for each searchable class using intuitive block-based API
@@ -123,9 +128,7 @@ me so I can rectify the situation!
123
128
 
124
129
  1. RSolr
125
130
  2. Daemons
126
- 3. OptiFlag
127
- 4. Haml
128
- 5. Java
131
+ 4. Java
129
132
 
130
133
  Sunspot has been tested with MRI 1.8.6 and 1.8.7, REE 1.8.6, YARV 1.9.1, and
131
134
  JRuby 1.2.0
@@ -135,6 +138,35 @@ JRuby 1.2.0
135
138
  Please submit bug reports to
136
139
  http://outoftime.lighthouseapp.com/projects/20339-sunspot
137
140
 
141
+ == Contribution Guidelines
142
+
143
+ Contributions are very welcome - both new features, enhancements, and bug fixes.
144
+ Bug reports with a failing regression test are also lovely. In order to keep the
145
+ contribution process as organized and smooth as possible, please follow these
146
+ guidelines:
147
+
148
+ * Contributions should be submitted via Sunspot's Lighthouse account, with an
149
+ attached git patch. See below for how to create a git patch.
150
+ * Patches should not make any changes in your patch to the gemspec task other
151
+ than adding/removing dependencies (e.g., changing the name, version, email,
152
+ description, etc.)
153
+ * Patches should not include any changes to the gemspec itself.
154
+ * Document any new methods, options, arguments, etc.
155
+ * Write tests.
156
+ * As much as possible, follow the coding and testing styles you see in existing
157
+ code. One could accuse me of being nitpicky about this, but consistent code is
158
+ easier to read, maintain, and enhance.
159
+ * Don't make any massive changes to the structure of library or test code. If
160
+ you think something needs a huge refactor or rearrangement, shoot me a
161
+ message; trying to apply that kind of patch without warning opens the door to
162
+ a world of conflict hurt.
163
+
164
+ Here's how to create a Git patch - assuming you're pulling from the canonical
165
+ Sunspot repository at `upstream`:
166
+
167
+ git fetch upstream
168
+ git format-patch upstre
169
+
138
170
  == Further Reading
139
171
 
140
172
  * Sunspot Discussion: http://groups.google.com/group/ruby-sunspot
@@ -148,6 +180,11 @@ http://outoftime.lighthouseapp.com/projects/20339-sunspot
148
180
  * Peer Allan (peer.allan@gmail.com)
149
181
  * Dmitriy Dzema (dima@dzema.name)
150
182
  * Benjamin Krause (bk@benjaminkrause.com)
183
+ * Marcel de Graaf (marcel@slashdev.nl)
184
+ * Brandon Keepers (brandon@opensoul.org)
185
+ * Peter Berkenbosch (peterberkenbosch@me.com)
186
+ * Brian Atkinson
187
+ * Tom Coleman (tom@thesnail.org)
151
188
 
152
189
  == License
153
190
 
data/TODO CHANGED
@@ -1,9 +1,11 @@
1
- === 0.9.X ===
2
- * Deal with empty facet queries
3
- * Passing an integer into the second argument of dynamic_facet() when multiple facets are requested gives the wrong value
4
1
  === 0.10 ===
5
- * Highlighting
6
- * LocalSolr
7
- * Text field restrictions
8
- * Prefixes
9
- * Intelligently decide whether to instantiate all facet rows at once
2
+ * Wrap everything into :q parameter when local search performed
3
+ * Allow boosting without field constraints
4
+ * Allow coordinates to be specified with block in setup
5
+ === 0.11 ===
6
+ * Support all operations in batches. Make it smart.
7
+ * Don't use more than one commits when one is equivalent
8
+ * Preserve adds/deletes that are done after last commit
9
+ * Don't do adds and deletes for the same document out of order
10
+ * Don't do more than one add for the same document
11
+ * Do use as few requests as possible within those constraints
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 9
3
- :patch: 8
2
+ :minor: 10
3
+ :patch: 0
4
4
  :major: 0
@@ -1,39 +1,33 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- using_gems = false
4
- begin
5
- require 'fileutils'
6
- require 'optiflag'
7
- require File.join(File.dirname(__FILE__), '..', 'lib', 'sunspot', 'schema')
8
- rescue LoadError => e
9
- if using_gems
10
- raise(e)
11
- else
12
- using_gems = true
13
- require 'rubygems'
14
- retry
3
+ require 'fileutils'
4
+ require 'optparse'
5
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sunspot', 'schema')
6
+
7
+ solr_directory = FileUtils.pwd
8
+
9
+ schema = Sunspot::Schema.new
10
+
11
+ OptionParser.new do |opts|
12
+ opts.banner = 'Usage: sunspot-configure-solr [options]'
13
+
14
+ opts.on '--tokenizer=TOKENIZER', 'Tokenizer class to use' do |tokenizer|
15
+ schema.tokenizer = tokenizer
15
16
  end
16
- end
17
17
 
18
- module ConfigureSolrFlags extend OptiFlagSet
19
- optional_flag 'tokenizer'
20
- optional_flag 'extra_filters'
21
- optional_flag 'dir'
22
- and_process!
23
- end
18
+ opts.on '--extra-filter=EXTRA_FILTER', 'Extra filters for tokenized text (you may specify this multiple times)' do |extra_filter|
19
+ schema.add_filter(extra_filter)
20
+ end
21
+
22
+ opts.on '--dir=CONF_DIR', 'Directory containing Solr configuration and schema' do |dir|
23
+ solr_directory = File.expand_path(dir)
24
+ end
25
+ end.parse!
24
26
 
25
- solr_directory = ARGV.flags.dir || FileUtils.pwd
26
27
  conf_directory = File.join(solr_directory, 'conf')
27
28
  schema_file = File.join(conf_directory, 'schema.xml')
28
- FileUtils.mkdir_p(conf_directory)
29
29
 
30
- schema = Sunspot::Schema.new
31
- schema.tokenizer = ARGV.flags.tokenizer if ARGV.flags.tokenizer
32
- if ARGV.flags.extra_filters
33
- for filter in ARGV.flags.extra_filters.split(',')
34
- schema.add_filter(filter)
35
- end
36
- end
30
+ FileUtils.mkdir_p(conf_directory)
37
31
 
38
32
  if File.exist?(schema_file)
39
33
  backup_file = File.join(conf_directory, "schema-#{File.mtime(schema_file).strftime('%Y%m%d%H%M%S')}.xml")
data/bin/sunspot-solr CHANGED
@@ -2,9 +2,10 @@
2
2
  using_gems = false
3
3
  begin
4
4
  require 'fileutils'
5
+ require 'tempfile'
5
6
  require 'tmpdir'
7
+ require 'optparse'
6
8
  require 'daemons'
7
- require 'optiflag'
8
9
  rescue LoadError => e
9
10
  if using_gems
10
11
  raise(e)
@@ -16,47 +17,67 @@ rescue LoadError => e
16
17
  end
17
18
 
18
19
  working_directory = FileUtils.pwd
19
- solr_home = File.join(File.dirname(__FILE__), '..', 'solr')
20
+ solr_home = File.expand_path(File.join(File.dirname(__FILE__), '..', 'solr'))
20
21
 
21
- module SolrFlags extend OptiFlagSet
22
- optional_flag 'p' do
23
- description 'Port on which to run Solr (default 8983)'
24
- long_form 'port'
22
+ port = '8983'
23
+ data_dir = File.expand_path(File.join(Dir.tmpdir, 'solr_data'))
24
+ home = nil
25
+ pid_dir = working_directory
26
+ log_file = nil
27
+ log_level = 'OFF'
28
+
29
+ OptionParser.new do |opts|
30
+ opts.banner = "Usage: sunspot-solr start [options]"
31
+
32
+ opts.on '-p', '--port=PORT', 'Port on which to run Solr (default 8983)' do |p|
33
+ port = p
25
34
  end
26
35
 
27
- optional_flag 'd' do
28
- description 'Solr data directory'
36
+ opts.on '-d', '--data-directory=DIRECTORY', 'Solr data directory' do |d|
37
+ data_dir = File.expand_path(d)
29
38
  end
30
39
 
31
- optional_flag 's' do
32
- description 'Solr home (should contain conf/ directory)'
40
+ opts.on '-s', '--solr-home=HOME', 'Solr home directory (should contain conf/ directory)' do |s|
41
+ solr_home = File.expand_path(s)
33
42
  end
34
43
 
35
- optional_flag 'pd' do
36
- long_form 'pid-dir'
37
- description 'Directory for pid files'
44
+ opts.on '--pid-dir=PID_DIR', 'Directory for pid files' do |pd|
45
+ pid_dir = File.expand_path(pd)
38
46
  end
39
47
 
40
- and_process!
41
- end
48
+ opts.on '-l', '--log-level=LOG_LEVEL', 'Solr logging level' do |l|
49
+ log_level = l
50
+ end
42
51
 
43
- port = ARGV.flags.p || '8983'
44
- data_dir = File.expand_path(ARGV.flags.d || File.join(Dir.tmpdir, 'solr_data'))
45
- home = File.expand_path(ARGV.flags.s) if ARGV.flags.s
46
- pid_dir = File.expand_path(ARGV.flags.pd || working_directory)
52
+ opts.on '--log-file=LOG_FILE', 'Path to Solr log file' do |lf|
53
+ log_file = File.expand_path(lf)
54
+ end
55
+ end.parse!
47
56
 
48
57
  options = { :dir_mode => :normal, :dir => pid_dir }
49
58
 
59
+ def logging_properties( log_file, log_level )
60
+ temp_file = Tempfile.new 'logging.properties'
61
+ temp_file << <<PROPERTIES
62
+ .level = #{log_level}
63
+ handlers = java.util.logging.FileHandler
64
+ java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
65
+ java.util.logging.FileHandler.pattern = #{log_file}
66
+ PROPERTIES
67
+ temp_file.flush
68
+ temp_file.close
69
+ temp_file.path
70
+ end
71
+
50
72
  Daemons.run_proc('sunspot-solr', options) do
51
- FileUtils.cd(working_directory) do
52
- FileUtils.cd(solr_home) do
53
- args = ['java']
54
- args << "-Djetty.port=#{port}" if port
55
- args << "-Dsolr.data.dir=#{data_dir}" if data_dir
56
- args << "-Dsolr.solr.home=#{home}" if home
57
- args << '-jar' << 'start.jar'
58
- STDERR.puts(args * ' ')
59
- Kernel.exec(*args)
60
- end
73
+ FileUtils.cd(solr_home) do
74
+ args = ['java']
75
+ args << "-Djetty.port=#{port}" if port
76
+ args << "-Dsolr.data.dir=#{data_dir}" if data_dir
77
+ args << "-Dsolr.solr.home=#{home}" if home
78
+ args << "-Djava.util.logging.config.file=#{logging_properties(log_file, log_level)}" if log_file and log_level != 'OFF'
79
+ args << '-jar' << 'start.jar'
80
+ STDERR.puts(args * ' ')
81
+ Kernel.exec(*args)
61
82
  end
62
83
  end
@@ -127,7 +127,7 @@ module Sunspot
127
127
  "No adapter is configured for #{original_class_name} or its superclasses. See the documentation for Sunspot::Adapters")
128
128
  end
129
129
 
130
- def index_id_for(class_name, id)
130
+ def index_id_for(class_name, id) #:nodoc:
131
131
  "#{class_name} #{id}"
132
132
  end
133
133
 
@@ -48,7 +48,7 @@ module Sunspot
48
48
  # UnrecognizedFieldError::
49
49
  # If no field with that name is configured for any of the enclosed types.
50
50
  #
51
- def text_field(field_name)
51
+ def text_fields(field_name)
52
52
  text_fields_hash[field_name.to_sym] || raise(
53
53
  UnrecognizedFieldError,
54
54
  "No text field configured for #{@types * ', '} with name '#{field_name}'"
@@ -104,8 +104,8 @@ module Sunspot
104
104
  #
105
105
  # Array:: Text fields configured for the enclosed types
106
106
  #
107
- def text_fields
108
- @text_fields ||= text_fields_hash.values
107
+ def all_text_fields
108
+ @text_fields ||= text_fields_hash.values.map { |set| set.to_a }.flatten
109
109
  end
110
110
 
111
111
  private
@@ -121,8 +121,8 @@ module Sunspot
121
121
  def text_fields_hash
122
122
  @text_fields_hash ||=
123
123
  setups.inject({}) do |hash, setup|
124
- setup.text_fields.each do |text_field|
125
- hash[text_field.name] ||= text_field
124
+ setup.all_text_fields.each do |text_field|
125
+ (hash[text_field.name] ||= Set.new) << text_field
126
126
  end
127
127
  hash
128
128
  end
@@ -141,21 +141,19 @@ module Sunspot
141
141
  def fields_hash
142
142
  @fields_hash ||=
143
143
  begin
144
- fields_hash = @types.inject({}) do |hash, type|
144
+ field_sets_hash = Hash.new { |h, k| h[k] = Set.new }
145
+ @types.each do |type|
145
146
  Setup.for(type).fields.each do |field|
146
- (hash[field.name.to_sym] ||= {})[type.name] = field
147
+ field_sets_hash[field.name.to_sym] << field
147
148
  end
148
- hash
149
149
  end
150
- fields_hash.each_pair do |field_name, field_configurations_hash|
151
- if @types.any? { |type| field_configurations_hash[type.name].nil? } # at least one type doesn't have this field configured
152
- fields_hash.delete(field_name)
153
- elsif field_configurations_hash.values.map { |configuration| configuration.indexed_name }.uniq.length != 1 # fields with this name have different configs
154
- fields_hash.delete(field_name)
155
- else
156
- fields_hash[field_name] = field_configurations_hash.values.first
150
+ fields_hash = {}
151
+ field_sets_hash.each_pair do |field_name, set|
152
+ if set.length == 1
153
+ fields_hash[field_name] = set.to_a.first
157
154
  end
158
155
  end
156
+ fields_hash
159
157
  end
160
158
  end
161
159
 
@@ -28,11 +28,25 @@ module Sunspot
28
28
  solr do
29
29
  url 'http://127.0.0.1:8983/solr'
30
30
  end
31
+ master_solr do
32
+ url nil
33
+ end
31
34
  pagination do
32
35
  default_per_page 30
33
36
  end
34
37
  end
35
38
  end
39
+
40
+ # Location for the default solr configuration files,
41
+ # required for bootstrapping a new solr installation
42
+ #
43
+ # ==== Returns
44
+ #
45
+ # String:: Directory with default solr config files
46
+ #
47
+ def solr_default_configuration_location
48
+ File.join( File.dirname(__FILE__), '../../solr/solr/conf' )
49
+ end
36
50
  end
37
51
  end
38
52
  end
@@ -34,6 +34,9 @@ module Sunspot
34
34
  end
35
35
  end
36
36
 
37
+ #
38
+ # Constant data extractors simply return the same value for every object.
39
+ #
37
40
  class Constant
38
41
  def initialize(value)
39
42
  @value = value
@@ -6,6 +6,11 @@ module Sunspot
6
6
  # query DSL.
7
7
  #
8
8
  class FieldQuery < Scope
9
+ def initialize(query, setup)
10
+ @query = query
11
+ super(query.scope, setup)
12
+ end
13
+
9
14
  # Specify the order that results should be returned in. This method can
10
15
  # be called multiple times; precedence will be in the order given.
11
16
  #
@@ -15,15 +20,22 @@ module Sunspot
15
20
  # direction<Symbol>:: :asc or :desc (default :asc)
16
21
  #
17
22
  def order_by(field_name, direction = nil)
18
- @query.order_by(field_name, direction)
23
+ sort =
24
+ if special = Sunspot::Query::Sort.special(field_name)
25
+ special.new(direction)
26
+ else
27
+ Sunspot::Query::Sort::FieldSort.new(
28
+ @setup.field(field_name), direction
29
+ )
30
+ end
31
+ @query.add_sort(sort)
19
32
  end
20
33
 
21
34
  #
22
- # Order results randomly. This will (generally) return the results in a
23
- # different order each time a search is called.
35
+ # DEPRECATED Use <code>order_by(:random)</code>
24
36
  #
25
37
  def order_by_random
26
- @query.order_by_random
38
+ order_by(:random)
27
39
  end
28
40
 
29
41
  # Request facets on the given field names. If the last argument is a hash,
@@ -49,6 +61,12 @@ module Sunspot
49
61
  #
50
62
  def facet(*field_names, &block)
51
63
  if block
64
+ options =
65
+ if field_names.last.is_a?(Hash)
66
+ field_names.pop
67
+ else
68
+ {}
69
+ end
52
70
  if field_names.length != 1
53
71
  raise(
54
72
  ArgumentError,
@@ -56,17 +74,26 @@ module Sunspot
56
74
  )
57
75
  end
58
76
  name = field_names.first
59
- DSL::QueryFacet.new(@query.add_query_facet(name)).instance_eval(&block)
77
+ DSL::QueryFacet.new(@query.add_query_facet(name, options), @setup).instance_eval(&block)
60
78
  else
61
79
  options =
62
80
  if field_names.last.is_a?(Hash)
63
81
  field_names.pop
82
+ else
83
+ {}
64
84
  end
65
85
  for field_name in field_names
66
- @query.add_field_facet(field_name, options)
86
+ @query.add_field_facet(@setup.field(field_name), options)
67
87
  end
68
88
  end
69
89
  end
90
+
91
+ def dynamic(base_name, &block)
92
+ Sunspot::Util.instance_eval_or_call(
93
+ FieldQuery.new(@query, @setup.dynamic_field_factory(base_name)),
94
+ &block
95
+ )
96
+ end
70
97
  end
71
98
  end
72
99
  end
@@ -26,7 +26,11 @@ module Sunspot
26
26
  # ==== Options
27
27
  #
28
28
  # :boost<Float>::
29
- # Boost that should be applied to this field for keyword search
29
+ # Index-time boost that should be applied to this field for keyword search
30
+ # :default_boost<Float>::
31
+ # Default search-time boost to apply to this field during keyword
32
+ # search. Can be overriden with DSL::Fulltext#fields or
33
+ # DSL::Fulltext#boost_fields method.
30
34
  #
31
35
  def text(*names, &block)
32
36
  options = names.pop if names.last.is_a?(Hash)
@@ -39,6 +43,15 @@ module Sunspot
39
43
  end
40
44
  end
41
45
 
46
+ #
47
+ # Specify a method that returns the geographical coordinates associated
48
+ # with the document. The object returned must respond to #first and #last
49
+ # (e.g., a two-element Array); or to #lat and one of #lng, #lon, or #long
50
+ #
51
+ def coordinates(name)
52
+ @setup.set_coordinates_field(name)
53
+ end
54
+
42
55
  #
43
56
  # Specify a document-level boost. As with fields, you have the option of
44
57
  # passing an attribute name which will be called on each model, or a block