sunspot 0.9.8 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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