sunspot 2.0.0 → 2.5.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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/Appraisals +7 -0
- data/Gemfile +0 -2
- data/History.txt +10 -0
- data/lib/sunspot.rb +55 -17
- data/lib/sunspot/adapters.rb +68 -18
- data/lib/sunspot/batcher.rb +1 -1
- data/lib/sunspot/configuration.rb +4 -2
- data/lib/sunspot/data_extractor.rb +36 -6
- data/lib/sunspot/dsl.rb +4 -3
- data/lib/sunspot/dsl/adjustable.rb +2 -2
- data/lib/sunspot/dsl/field_query.rb +69 -16
- data/lib/sunspot/dsl/field_stats.rb +25 -0
- data/lib/sunspot/dsl/fields.rb +28 -8
- data/lib/sunspot/dsl/fulltext.rb +9 -1
- data/lib/sunspot/dsl/group.rb +118 -0
- data/lib/sunspot/dsl/paginatable.rb +4 -1
- data/lib/sunspot/dsl/scope.rb +19 -10
- data/lib/sunspot/dsl/search.rb +1 -1
- data/lib/sunspot/dsl/spellcheckable.rb +14 -0
- data/lib/sunspot/dsl/standard_query.rb +63 -35
- data/lib/sunspot/field.rb +76 -4
- data/lib/sunspot/field_factory.rb +60 -11
- data/lib/sunspot/indexer.rb +70 -18
- data/lib/sunspot/query.rb +5 -4
- data/lib/sunspot/query/abstract_field_facet.rb +0 -2
- data/lib/sunspot/query/abstract_fulltext.rb +76 -0
- data/lib/sunspot/query/abstract_json_field_facet.rb +70 -0
- data/lib/sunspot/query/bbox.rb +5 -1
- data/lib/sunspot/query/common_query.rb +31 -6
- data/lib/sunspot/query/composite_fulltext.rb +58 -8
- data/lib/sunspot/query/date_field_json_facet.rb +25 -0
- data/lib/sunspot/query/dismax.rb +25 -71
- data/lib/sunspot/query/field_json_facet.rb +19 -0
- data/lib/sunspot/query/field_list.rb +15 -0
- data/lib/sunspot/query/field_stats.rb +61 -0
- data/lib/sunspot/query/function_query.rb +1 -2
- data/lib/sunspot/query/geo.rb +1 -1
- data/lib/sunspot/query/geofilt.rb +8 -3
- data/lib/sunspot/query/group.rb +46 -0
- data/lib/sunspot/query/group_query.rb +17 -0
- data/lib/sunspot/query/join.rb +88 -0
- data/lib/sunspot/query/more_like_this.rb +1 -1
- data/lib/sunspot/query/pagination.rb +12 -4
- data/lib/sunspot/query/range_json_facet.rb +28 -0
- data/lib/sunspot/query/restriction.rb +99 -13
- data/lib/sunspot/query/sort.rb +41 -0
- data/lib/sunspot/query/sort_composite.rb +7 -0
- data/lib/sunspot/query/spellcheck.rb +19 -0
- data/lib/sunspot/query/standard_query.rb +24 -2
- data/lib/sunspot/query/text_field_boost.rb +1 -3
- data/lib/sunspot/schema.rb +12 -3
- data/lib/sunspot/search.rb +4 -2
- data/lib/sunspot/search/abstract_search.rb +93 -43
- data/lib/sunspot/search/cursor_paginated_collection.rb +32 -0
- data/lib/sunspot/search/field_facet.rb +4 -4
- data/lib/sunspot/search/field_json_facet.rb +33 -0
- data/lib/sunspot/search/field_stats.rb +21 -0
- data/lib/sunspot/search/hit.rb +6 -1
- data/lib/sunspot/search/hit_enumerable.rb +4 -1
- data/lib/sunspot/search/json_facet_row.rb +40 -0
- data/lib/sunspot/search/json_facet_stats.rb +23 -0
- data/lib/sunspot/search/paginated_collection.rb +1 -0
- data/lib/sunspot/search/query_group.rb +74 -0
- data/lib/sunspot/search/standard_search.rb +70 -3
- data/lib/sunspot/search/stats_facet.rb +25 -0
- data/lib/sunspot/search/stats_json_row.rb +82 -0
- data/lib/sunspot/search/stats_row.rb +68 -0
- data/lib/sunspot/session.rb +62 -37
- data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +6 -4
- data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +16 -8
- data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +2 -2
- data/lib/sunspot/session_proxy/retry_5xx_session_proxy.rb +1 -1
- data/lib/sunspot/session_proxy/sharding_session_proxy.rb +4 -2
- data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +1 -1
- data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +6 -4
- data/lib/sunspot/setup.rb +42 -0
- data/lib/sunspot/type.rb +20 -0
- data/lib/sunspot/util.rb +78 -14
- data/lib/sunspot/version.rb +1 -1
- data/spec/api/adapters_spec.rb +40 -15
- data/spec/api/batcher_spec.rb +15 -15
- data/spec/api/binding_spec.rb +3 -3
- data/spec/api/class_set_spec.rb +6 -6
- data/spec/api/data_extractor_spec.rb +39 -0
- data/spec/api/hit_enumerable_spec.rb +32 -9
- data/spec/api/indexer/attributes_spec.rb +35 -30
- data/spec/api/indexer/batch_spec.rb +8 -7
- data/spec/api/indexer/dynamic_fields_spec.rb +8 -8
- data/spec/api/indexer/fixed_fields_spec.rb +16 -11
- data/spec/api/indexer/fulltext_spec.rb +8 -8
- data/spec/api/indexer/removal_spec.rb +24 -14
- data/spec/api/indexer_spec.rb +2 -2
- data/spec/api/query/advanced_manipulation_examples.rb +3 -3
- data/spec/api/query/connectives_examples.rb +26 -14
- data/spec/api/query/dsl_spec.rb +24 -6
- data/spec/api/query/dynamic_fields_examples.rb +18 -18
- data/spec/api/query/faceting_examples.rb +80 -61
- data/spec/api/query/fulltext_examples.rb +194 -40
- data/spec/api/query/function_spec.rb +116 -13
- data/spec/api/query/geo_examples.rb +8 -12
- data/spec/api/query/group_spec.rb +27 -5
- data/spec/api/query/highlighting_examples.rb +26 -26
- data/spec/api/query/join_spec.rb +19 -0
- data/spec/api/query/more_like_this_spec.rb +40 -27
- data/spec/api/query/ordering_pagination_examples.rb +37 -23
- data/spec/api/query/scope_examples.rb +39 -39
- data/spec/api/query/spatial_examples.rb +3 -3
- data/spec/api/query/spellcheck_examples.rb +20 -0
- data/spec/api/query/standard_spec.rb +3 -1
- data/spec/api/query/stats_examples.rb +66 -0
- data/spec/api/query/text_field_scoping_examples.rb +5 -5
- data/spec/api/query/types_spec.rb +4 -4
- data/spec/api/search/cursor_paginated_collection_spec.rb +35 -0
- data/spec/api/search/dynamic_fields_spec.rb +4 -4
- data/spec/api/search/faceting_spec.rb +55 -52
- data/spec/api/search/highlighting_spec.rb +7 -7
- data/spec/api/search/hits_spec.rb +43 -29
- data/spec/api/search/paginated_collection_spec.rb +19 -18
- data/spec/api/search/results_spec.rb +13 -13
- data/spec/api/search/search_spec.rb +3 -3
- data/spec/api/search/stats_spec.rb +94 -0
- data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +23 -16
- data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +16 -4
- data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +10 -6
- data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +11 -11
- data/spec/api/session_proxy/sharding_session_proxy_spec.rb +15 -14
- data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +3 -3
- data/spec/api/session_proxy/spec_helper.rb +1 -1
- data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +40 -26
- data/spec/api/session_spec.rb +78 -38
- data/spec/api/sunspot_spec.rb +7 -4
- data/spec/helpers/integration_helper.rb +11 -1
- data/spec/helpers/query_helper.rb +1 -1
- data/spec/helpers/search_helper.rb +30 -0
- data/spec/integration/atomic_updates_spec.rb +58 -0
- data/spec/integration/dynamic_fields_spec.rb +31 -20
- data/spec/integration/faceting_spec.rb +252 -39
- data/spec/integration/field_grouping_spec.rb +47 -15
- data/spec/integration/field_lists_spec.rb +57 -0
- data/spec/integration/geospatial_spec.rb +34 -8
- data/spec/integration/highlighting_spec.rb +8 -8
- data/spec/integration/indexing_spec.rb +7 -6
- data/spec/integration/join_spec.rb +45 -0
- data/spec/integration/keyword_search_spec.rb +68 -38
- data/spec/integration/local_search_spec.rb +4 -4
- data/spec/integration/more_like_this_spec.rb +7 -7
- data/spec/integration/scoped_search_spec.rb +193 -74
- data/spec/integration/spellcheck_spec.rb +119 -0
- data/spec/integration/stats_spec.rb +88 -0
- data/spec/integration/stored_fields_spec.rb +1 -1
- data/spec/integration/test_pagination.rb +4 -4
- data/spec/integration/unicode_spec.rb +1 -1
- data/spec/mocks/adapters.rb +36 -0
- data/spec/mocks/connection.rb +5 -3
- data/spec/mocks/photo.rb +32 -1
- data/spec/mocks/post.rb +18 -3
- data/spec/spec_helper.rb +13 -8
- data/sunspot.gemspec +6 -4
- data/tasks/rdoc.rake +22 -14
- metadata +101 -44
- data/lib/sunspot/dsl/field_group.rb +0 -57
- data/lib/sunspot/query/field_group.rb +0 -37
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Sunspot
|
|
2
2
|
module DSL
|
|
3
|
-
#
|
|
3
|
+
#
|
|
4
4
|
# Provides an API for areas of the query DSL that operate on specific
|
|
5
5
|
# fields. This functionality is provided by the query DSL and the dynamic
|
|
6
6
|
# query DSL.
|
|
@@ -45,14 +45,14 @@ module Sunspot
|
|
|
45
45
|
# the reference longitude
|
|
46
46
|
# direction<Symbol>::
|
|
47
47
|
# :asc or :desc (default :asc)
|
|
48
|
-
#
|
|
48
|
+
#
|
|
49
49
|
def order_by_geodist(field_name, lat, lon, direction = nil)
|
|
50
50
|
@query.add_sort(
|
|
51
51
|
Sunspot::Query::Sort::GeodistSort.new(@setup.field(field_name), lat, lon, direction)
|
|
52
52
|
)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
#
|
|
55
|
+
#
|
|
56
56
|
# DEPRECATED Use <code>order_by(:random)</code>
|
|
57
57
|
#
|
|
58
58
|
def order_by_random
|
|
@@ -68,20 +68,22 @@ module Sunspot
|
|
|
68
68
|
#
|
|
69
69
|
# ==== Parameters
|
|
70
70
|
#
|
|
71
|
-
#
|
|
71
|
+
# field_names...<Symbol>:: the fields to use for grouping
|
|
72
72
|
def group(*field_names, &block)
|
|
73
|
+
group = Sunspot::Query::Group.new()
|
|
74
|
+
|
|
73
75
|
field_names.each do |field_name|
|
|
74
76
|
field = @setup.field(field_name)
|
|
75
|
-
group
|
|
76
|
-
|
|
77
|
+
group.add_field(field)
|
|
78
|
+
end
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
&block
|
|
82
|
-
)
|
|
83
|
-
end
|
|
80
|
+
if block
|
|
81
|
+
dsl = Group.new(@setup, group)
|
|
82
|
+
Sunspot::Util.instance_eval_or_call(dsl, &block)
|
|
84
83
|
end
|
|
84
|
+
|
|
85
|
+
@query.add_group(group)
|
|
86
|
+
@search.add_group(group)
|
|
85
87
|
end
|
|
86
88
|
|
|
87
89
|
#
|
|
@@ -109,7 +111,7 @@ module Sunspot
|
|
|
109
111
|
# with(:blog_id, 1)
|
|
110
112
|
# facet(:category_id)
|
|
111
113
|
# end
|
|
112
|
-
#
|
|
114
|
+
#
|
|
113
115
|
# The facet specified above will have a row for each category_id that is
|
|
114
116
|
# present in a document which also has a blog_id of 1.
|
|
115
117
|
#
|
|
@@ -125,12 +127,12 @@ module Sunspot
|
|
|
125
127
|
# category_filter = with(:category_id, 2)
|
|
126
128
|
# facet(:category_id, :exclude => category_filter)
|
|
127
129
|
# end
|
|
128
|
-
#
|
|
130
|
+
#
|
|
129
131
|
# Although the results of the above search will be restricted to those
|
|
130
132
|
# with a category_id of 2, the category_id facet will operate as if a
|
|
131
133
|
# category had not been selected, allowing the user to select additional
|
|
132
134
|
# categories (which will presumably be ORed together).
|
|
133
|
-
#
|
|
135
|
+
#
|
|
134
136
|
# It possible to exclude multiple filters by passing an array:
|
|
135
137
|
#
|
|
136
138
|
# Sunspot.search(Post) do
|
|
@@ -141,7 +143,7 @@ module Sunspot
|
|
|
141
143
|
# :exclude => [category_filter, author_filter].compact)
|
|
142
144
|
# end
|
|
143
145
|
#
|
|
144
|
-
# You should consider using +.compact+ to ensure that the array does not
|
|
146
|
+
# You should consider using +.compact+ to ensure that the array does not
|
|
145
147
|
# contain any nil values.
|
|
146
148
|
#
|
|
147
149
|
# <strong>As far as I can tell, Solr only supports multi-select with
|
|
@@ -331,6 +333,33 @@ module Sunspot
|
|
|
331
333
|
end
|
|
332
334
|
end
|
|
333
335
|
|
|
336
|
+
def json_facet(*field_names)
|
|
337
|
+
options = Sunspot::Util.extract_options_from(field_names)
|
|
338
|
+
|
|
339
|
+
field_names.each do |field_name|
|
|
340
|
+
field = @setup.field(field_name)
|
|
341
|
+
facet = Sunspot::Util.parse_json_facet(field_name, options, @setup)
|
|
342
|
+
@search.add_json_facet(field, options)
|
|
343
|
+
@query.add_query_facet(facet)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def stats(*field_names, &block)
|
|
348
|
+
options = Sunspot::Util.extract_options_from(field_names)
|
|
349
|
+
|
|
350
|
+
field_names.each do |field_name|
|
|
351
|
+
field = @setup.field(field_name)
|
|
352
|
+
query_stats = @query.add_stats(
|
|
353
|
+
Sunspot::Query::FieldStats.new(field, options)
|
|
354
|
+
)
|
|
355
|
+
search_stats = @search.add_field_stats(field)
|
|
356
|
+
|
|
357
|
+
Sunspot::Util.instance_eval_or_call(
|
|
358
|
+
FieldStats.new(query_stats, @setup, search_stats),
|
|
359
|
+
&block) if block
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
334
363
|
def dynamic(base_name, &block)
|
|
335
364
|
dynamic_field_factory = @setup.dynamic_field_factory(base_name)
|
|
336
365
|
Sunspot::Util.instance_eval_or_call(
|
|
@@ -338,6 +367,30 @@ module Sunspot
|
|
|
338
367
|
&block
|
|
339
368
|
)
|
|
340
369
|
end
|
|
370
|
+
#
|
|
371
|
+
# Specify that results should be ordered based on a
|
|
372
|
+
# FunctionQuery - http://wiki.apache.org/solr/FunctionQuery
|
|
373
|
+
# Solr 3.1 and up
|
|
374
|
+
#
|
|
375
|
+
# For example, to order by field1 + (field2*field3):
|
|
376
|
+
#
|
|
377
|
+
# order_by_function :sum, :field1, [:product, :field2, :field3], :desc
|
|
378
|
+
#
|
|
379
|
+
# ==== Parameters
|
|
380
|
+
# function_name<Symbol>::
|
|
381
|
+
# the function to run
|
|
382
|
+
# arguments::
|
|
383
|
+
# the arguments for this function.
|
|
384
|
+
# - Symbol for a field or function name
|
|
385
|
+
# - Array for a nested function
|
|
386
|
+
# - String for a literal constant
|
|
387
|
+
# direction<Symbol>::
|
|
388
|
+
# :asc or :desc
|
|
389
|
+
def order_by_function(*args)
|
|
390
|
+
@query.add_sort(
|
|
391
|
+
Sunspot::Query::Sort::FunctionSort.new(@setup,args)
|
|
392
|
+
)
|
|
393
|
+
end
|
|
341
394
|
end
|
|
342
395
|
end
|
|
343
396
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Sunspot
|
|
2
|
+
module DSL
|
|
3
|
+
class FieldStats #:nodoc:
|
|
4
|
+
def initialize(query_stats, setup, search_stats) #:nodoc:
|
|
5
|
+
@query_stats, @setup, @search_stats = query_stats, setup, search_stats
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def facet *field_names
|
|
9
|
+
field_names.each do |field_name|
|
|
10
|
+
field = @setup.field(field_name)
|
|
11
|
+
|
|
12
|
+
@query_stats.add_facet(field)
|
|
13
|
+
@search_stats.add_facet(field)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def json_facet(field_name, options = {})
|
|
18
|
+
field = @setup.field(field_name)
|
|
19
|
+
facet = Sunspot::Util.parse_json_facet(field_name, options, @setup)
|
|
20
|
+
@query_stats.add_json_facet(facet)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/sunspot/dsl/fields.rb
CHANGED
|
@@ -33,13 +33,10 @@ module Sunspot
|
|
|
33
33
|
# DSL::Fulltext#boost_fields method.
|
|
34
34
|
#
|
|
35
35
|
def text(*names, &block)
|
|
36
|
-
options = names.
|
|
36
|
+
options = names.last.is_a?(Hash) ? names.pop : {}
|
|
37
|
+
|
|
37
38
|
names.each do |name|
|
|
38
|
-
@setup.add_text_field_factory(
|
|
39
|
-
name,
|
|
40
|
-
options || {},
|
|
41
|
-
&block
|
|
42
|
-
)
|
|
39
|
+
@setup.add_text_field_factory(name, options, &block)
|
|
43
40
|
end
|
|
44
41
|
end
|
|
45
42
|
|
|
@@ -58,6 +55,22 @@ module Sunspot
|
|
|
58
55
|
@setup.add_document_boost(attr_name, &block)
|
|
59
56
|
end
|
|
60
57
|
|
|
58
|
+
#
|
|
59
|
+
# If you use the compositeId router for shards, you can send documents
|
|
60
|
+
# with a prefix in the document ID which will be used to calculate the
|
|
61
|
+
# hash Solr uses to determine the shard a document is sent to for indexing.
|
|
62
|
+
# The prefix can be anything you’d like it to be (it doesn’t have to be
|
|
63
|
+
# the shard name, for example), but it must be consistent so Solr
|
|
64
|
+
# behaves consistently.
|
|
65
|
+
#
|
|
66
|
+
# ==== Parameters
|
|
67
|
+
#
|
|
68
|
+
# attr_name<Symbol,String>:: Attribute name to call or a string constant
|
|
69
|
+
#
|
|
70
|
+
def id_prefix(attr_name = nil, &block)
|
|
71
|
+
@setup.add_id_prefix(attr_name, &block)
|
|
72
|
+
end
|
|
73
|
+
|
|
61
74
|
# method_missing is used to provide access to typed fields, because
|
|
62
75
|
# developers should be able to add new Sunspot::Type implementations
|
|
63
76
|
# dynamically and have them recognized inside the Fields DSL. Like #text,
|
|
@@ -74,26 +87,33 @@ module Sunspot
|
|
|
74
87
|
#
|
|
75
88
|
def method_missing(method, *args, &block)
|
|
76
89
|
options = Util.extract_options_from(args)
|
|
77
|
-
|
|
90
|
+
join = method.to_s == 'join'
|
|
91
|
+
type_string = join ? options.delete(:type).to_s : method.to_s
|
|
92
|
+
type_const_name = "#{Util.camel_case(type_string.sub(/^dynamic_/, ''))}Type"
|
|
78
93
|
trie = options.delete(:trie)
|
|
79
94
|
type_const_name = "Trie#{type_const_name}" if trie
|
|
95
|
+
|
|
80
96
|
begin
|
|
81
97
|
type_class = Type.const_get(type_const_name)
|
|
82
|
-
rescue
|
|
98
|
+
rescue NameError
|
|
83
99
|
if trie
|
|
84
100
|
raise ArgumentError, "Trie fields are only valid for numeric and time types"
|
|
85
101
|
else
|
|
86
102
|
super(method, *args, &block)
|
|
87
103
|
end
|
|
88
104
|
end
|
|
105
|
+
|
|
89
106
|
type = type_class.instance
|
|
90
107
|
name = args.shift
|
|
108
|
+
|
|
91
109
|
if method.to_s =~ /^dynamic_/
|
|
92
110
|
if type.accepts_dynamic?
|
|
93
111
|
@setup.add_dynamic_field_factory(name, type, options, &block)
|
|
94
112
|
else
|
|
95
113
|
super(method, *args, &block)
|
|
96
114
|
end
|
|
115
|
+
elsif join
|
|
116
|
+
@setup.add_join_field_factory(name, type, options.merge(:clazz => @setup.clazz), &block)
|
|
97
117
|
else
|
|
98
118
|
@setup.add_field_factory(name, type, options, &block)
|
|
99
119
|
end
|
data/lib/sunspot/dsl/fulltext.rb
CHANGED
|
@@ -168,8 +168,12 @@ module Sunspot
|
|
|
168
168
|
# will be boosted by (average_rating + popularity * 10).
|
|
169
169
|
#
|
|
170
170
|
def boost(factor_or_function, &block)
|
|
171
|
+
additive_boost(factor_or_function, &block)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def additive_boost(factor_or_function, &block)
|
|
171
175
|
if factor_or_function.is_a?(Sunspot::Query::FunctionQuery)
|
|
172
|
-
@query.
|
|
176
|
+
@query.add_additive_boost_function(factor_or_function)
|
|
173
177
|
else
|
|
174
178
|
Sunspot::Util.instance_eval_or_call(
|
|
175
179
|
Scope.new(@query.create_boost_query(factor_or_function), @setup),
|
|
@@ -178,6 +182,10 @@ module Sunspot
|
|
|
178
182
|
end
|
|
179
183
|
end
|
|
180
184
|
|
|
185
|
+
def multiplicative_boost(factor_or_function)
|
|
186
|
+
@query.add_multiplicative_boost_function(factor_or_function)
|
|
187
|
+
end
|
|
188
|
+
|
|
181
189
|
#
|
|
182
190
|
# Add boost to certain fields, without restricting which fields are
|
|
183
191
|
# searched.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module Sunspot
|
|
2
|
+
module DSL
|
|
3
|
+
class Group
|
|
4
|
+
def initialize(setup, group)
|
|
5
|
+
@setup, @group = setup, group
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Specify one or more fields for result grouping.
|
|
9
|
+
#
|
|
10
|
+
# ==== Parameters
|
|
11
|
+
#
|
|
12
|
+
# field_names...<Symbol>:: the fields to use for grouping
|
|
13
|
+
#
|
|
14
|
+
def field(*field_names, &block)
|
|
15
|
+
field_names.each do |field_name|
|
|
16
|
+
field = @setup.field(field_name)
|
|
17
|
+
@group.add_field(field)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Specify a query to group results by.
|
|
22
|
+
#
|
|
23
|
+
# ==== Parameters
|
|
24
|
+
#
|
|
25
|
+
# label<Object>:: a label for this group; when #value is called on this
|
|
26
|
+
# group's results, this label will be returned.
|
|
27
|
+
#
|
|
28
|
+
def query(label, &block)
|
|
29
|
+
group_query = Sunspot::Query::GroupQuery.new(label)
|
|
30
|
+
Sunspot::Util.instance_eval_or_call(Scope.new(group_query, @setup), &block)
|
|
31
|
+
@group.add_query(group_query)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Sets the number of results (documents) to return for each group.
|
|
36
|
+
# Defaults to 1.
|
|
37
|
+
#
|
|
38
|
+
def limit(num)
|
|
39
|
+
@group.limit = num
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# If set, facet counts are based on the most relevant document of
|
|
44
|
+
# each group matching the query.
|
|
45
|
+
#
|
|
46
|
+
# Supported in Solr 3.4 and above.
|
|
47
|
+
#
|
|
48
|
+
# ==== Example
|
|
49
|
+
#
|
|
50
|
+
# Sunspot.search(Post) do
|
|
51
|
+
# group :title do
|
|
52
|
+
# truncate
|
|
53
|
+
# end
|
|
54
|
+
#
|
|
55
|
+
# facet :title, :extra => :any
|
|
56
|
+
# end
|
|
57
|
+
#
|
|
58
|
+
def truncate
|
|
59
|
+
@group.truncate = true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
# The group.ngroups option true return the total number of groups
|
|
64
|
+
# this is expensive and sometimes you don't need it!
|
|
65
|
+
# If ngroups is false paginated_collection last_page? and total_pages wont't work.
|
|
66
|
+
# Defaults to true.
|
|
67
|
+
#
|
|
68
|
+
def ngroups(enabled)
|
|
69
|
+
@group.ngroups = enabled
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Specify the order that results should be returned in. This method can
|
|
73
|
+
# be called multiple times; precedence will be in the order given.
|
|
74
|
+
#
|
|
75
|
+
# ==== Parameters
|
|
76
|
+
#
|
|
77
|
+
# field_name<Symbol>:: the field to use for ordering
|
|
78
|
+
# direction<Symbol>:: :asc or :desc (default :asc)
|
|
79
|
+
#
|
|
80
|
+
def order_by(field_name, direction = nil)
|
|
81
|
+
sort =
|
|
82
|
+
if special = Sunspot::Query::Sort.special(field_name)
|
|
83
|
+
special.new(direction)
|
|
84
|
+
else
|
|
85
|
+
Sunspot::Query::Sort::FieldSort.new(
|
|
86
|
+
@setup.field(field_name), direction
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
@group.add_sort(sort)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#
|
|
93
|
+
# Specify that results should be ordered based on a
|
|
94
|
+
# FunctionQuery - http://wiki.apache.org/solr/FunctionQuery
|
|
95
|
+
# Solr 3.1 and up
|
|
96
|
+
#
|
|
97
|
+
# For example, to order by field1 + (field2*field3):
|
|
98
|
+
#
|
|
99
|
+
# order_by_function :sum, :field1, [:product, :field2, :field3], :desc
|
|
100
|
+
#
|
|
101
|
+
# ==== Parameters
|
|
102
|
+
# function_name<Symbol>::
|
|
103
|
+
# the function to run
|
|
104
|
+
# arguments::
|
|
105
|
+
# the arguments for this function.
|
|
106
|
+
# - Symbol for a field or function name
|
|
107
|
+
# - Array for a nested function
|
|
108
|
+
# - String for a literal constant
|
|
109
|
+
# direction<Symbol>::
|
|
110
|
+
# :asc or :desc
|
|
111
|
+
def order_by_function(*args)
|
|
112
|
+
@group.add_sort(
|
|
113
|
+
Sunspot::Query::Sort::FunctionSort.new(@setup,args)
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -20,12 +20,15 @@ module Sunspot
|
|
|
20
20
|
# :offset<Integer,String>::
|
|
21
21
|
# Applies a shift to paginated records. The default is 0.
|
|
22
22
|
#
|
|
23
|
+
# :cursor<String>:: Cursor value for cursor-based pagination. The default is nil.
|
|
24
|
+
#
|
|
23
25
|
def paginate(options = {})
|
|
24
26
|
page = options.delete(:page)
|
|
25
27
|
per_page = options.delete(:per_page)
|
|
26
28
|
offset = options.delete(:offset)
|
|
29
|
+
cursor = options.delete(:cursor)
|
|
27
30
|
raise ArgumentError, "unknown argument #{options.keys.first.inspect} passed to paginate" unless options.empty?
|
|
28
|
-
@query.paginate(page, per_page, offset)
|
|
31
|
+
@query.paginate(page, per_page, offset, cursor)
|
|
29
32
|
end
|
|
30
33
|
end
|
|
31
34
|
end
|
data/lib/sunspot/dsl/scope.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Sunspot
|
|
2
2
|
module DSL #:nodoc:
|
|
3
|
-
#
|
|
3
|
+
#
|
|
4
4
|
# This DSL presents methods for constructing restrictions and other query
|
|
5
5
|
# elements that are specific to fields. As well as being a superclass of
|
|
6
6
|
# Sunspot::DSL::StandardQuery, which presents the main query block, this
|
|
@@ -12,7 +12,17 @@ module Sunspot
|
|
|
12
12
|
@scope, @setup = scope, setup
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
#
|
|
15
|
+
# Build a restriction to return only fields of the type in the results.
|
|
16
|
+
def field_list(*args)
|
|
17
|
+
list = args.flatten.map { |field| @setup.field(field.to_sym).indexed_name.to_sym }
|
|
18
|
+
@query.add_field_list(Sunspot::Query::FieldList.new([:id] + list)) unless list.empty?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def without_stored_fields
|
|
22
|
+
@query.add_field_list(Sunspot::Query::FieldList.new([:id]))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
16
26
|
# Build a positive restriction. This method can take three forms: equality
|
|
17
27
|
# restriction, restriction by another restriction, or identity
|
|
18
28
|
# restriction.
|
|
@@ -62,7 +72,7 @@ module Sunspot
|
|
|
62
72
|
# Sunspot.search do
|
|
63
73
|
# with(:category_ids, [1, 5, 9])
|
|
64
74
|
# end
|
|
65
|
-
#
|
|
75
|
+
#
|
|
66
76
|
# Other restriction types:
|
|
67
77
|
#
|
|
68
78
|
# Sunspot.search(Post) do
|
|
@@ -87,7 +97,7 @@ module Sunspot
|
|
|
87
97
|
add_restriction(true, *args)
|
|
88
98
|
end
|
|
89
99
|
|
|
90
|
-
#
|
|
100
|
+
#
|
|
91
101
|
# Create a disjunction, scoping the results to documents that match any
|
|
92
102
|
# of the enclosed restrictions.
|
|
93
103
|
#
|
|
@@ -109,7 +119,7 @@ module Sunspot
|
|
|
109
119
|
disjunction
|
|
110
120
|
end
|
|
111
121
|
|
|
112
|
-
#
|
|
122
|
+
#
|
|
113
123
|
# Create a conjunction, scoping the results to documents that match all of
|
|
114
124
|
# the enclosed restrictions. When called from the top level of a search
|
|
115
125
|
# block, this has no effect, but can be useful for grouping a conjunction
|
|
@@ -138,9 +148,9 @@ module Sunspot
|
|
|
138
148
|
# The block API is implemented by Sunspot::DSL::FieldQuery, which is a
|
|
139
149
|
# superclass of the Query DSL (thus providing a subset of the API, in
|
|
140
150
|
# particular only methods that refer to particular fields).
|
|
141
|
-
#
|
|
151
|
+
#
|
|
142
152
|
# ==== Parameters
|
|
143
|
-
#
|
|
153
|
+
#
|
|
144
154
|
# base_name<Symbol>:: The base name for the dynamic field definition
|
|
145
155
|
#
|
|
146
156
|
# ==== Example
|
|
@@ -160,14 +170,14 @@ module Sunspot
|
|
|
160
170
|
)
|
|
161
171
|
end
|
|
162
172
|
|
|
163
|
-
#
|
|
173
|
+
#
|
|
164
174
|
# Apply scope-type restrictions on fulltext fields. In certain situations,
|
|
165
175
|
# it may be desirable to place logical restrictions on text fields.
|
|
166
176
|
# Remember that text fields are tokenized; your mileage may very.
|
|
167
177
|
#
|
|
168
178
|
# The block works exactly like a normal scope, except that the field names
|
|
169
179
|
# refer to text fields instead of attribute fields.
|
|
170
|
-
#
|
|
180
|
+
#
|
|
171
181
|
# === Example
|
|
172
182
|
#
|
|
173
183
|
# Sunspot.search(Post) do
|
|
@@ -208,7 +218,6 @@ module Sunspot
|
|
|
208
218
|
)
|
|
209
219
|
end
|
|
210
220
|
end
|
|
211
|
-
|
|
212
221
|
end
|
|
213
222
|
end
|
|
214
223
|
end
|