gojee-sunspot 2.0.2

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 (176) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +5 -0
  3. data/History.txt +252 -0
  4. data/LICENSE +18 -0
  5. data/Rakefile +13 -0
  6. data/TODO +13 -0
  7. data/lib/light_config.rb +40 -0
  8. data/lib/sunspot.rb +579 -0
  9. data/lib/sunspot/adapters.rb +265 -0
  10. data/lib/sunspot/batcher.rb +62 -0
  11. data/lib/sunspot/class_set.rb +23 -0
  12. data/lib/sunspot/composite_setup.rb +202 -0
  13. data/lib/sunspot/configuration.rb +53 -0
  14. data/lib/sunspot/data_extractor.rb +50 -0
  15. data/lib/sunspot/dsl.rb +5 -0
  16. data/lib/sunspot/dsl/adjustable.rb +47 -0
  17. data/lib/sunspot/dsl/field_group.rb +57 -0
  18. data/lib/sunspot/dsl/field_query.rb +327 -0
  19. data/lib/sunspot/dsl/fields.rb +103 -0
  20. data/lib/sunspot/dsl/fulltext.rb +243 -0
  21. data/lib/sunspot/dsl/function.rb +27 -0
  22. data/lib/sunspot/dsl/functional.rb +44 -0
  23. data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
  24. data/lib/sunspot/dsl/paginatable.rb +32 -0
  25. data/lib/sunspot/dsl/query_facet.rb +36 -0
  26. data/lib/sunspot/dsl/restriction.rb +25 -0
  27. data/lib/sunspot/dsl/restriction_with_near.rb +160 -0
  28. data/lib/sunspot/dsl/scope.rb +217 -0
  29. data/lib/sunspot/dsl/search.rb +30 -0
  30. data/lib/sunspot/dsl/standard_query.rb +123 -0
  31. data/lib/sunspot/field.rb +193 -0
  32. data/lib/sunspot/field_factory.rb +129 -0
  33. data/lib/sunspot/indexer.rb +136 -0
  34. data/lib/sunspot/query.rb +11 -0
  35. data/lib/sunspot/query/abstract_field_facet.rb +52 -0
  36. data/lib/sunspot/query/bbox.rb +15 -0
  37. data/lib/sunspot/query/boost_query.rb +24 -0
  38. data/lib/sunspot/query/common_query.rb +96 -0
  39. data/lib/sunspot/query/composite_fulltext.rb +36 -0
  40. data/lib/sunspot/query/connective.rb +206 -0
  41. data/lib/sunspot/query/date_field_facet.rb +14 -0
  42. data/lib/sunspot/query/dismax.rb +132 -0
  43. data/lib/sunspot/query/field_facet.rb +41 -0
  44. data/lib/sunspot/query/field_group.rb +36 -0
  45. data/lib/sunspot/query/filter.rb +38 -0
  46. data/lib/sunspot/query/function_query.rb +52 -0
  47. data/lib/sunspot/query/geo.rb +53 -0
  48. data/lib/sunspot/query/geofilt.rb +16 -0
  49. data/lib/sunspot/query/highlighting.rb +62 -0
  50. data/lib/sunspot/query/more_like_this.rb +61 -0
  51. data/lib/sunspot/query/more_like_this_query.rb +12 -0
  52. data/lib/sunspot/query/pagination.rb +42 -0
  53. data/lib/sunspot/query/query_facet.rb +16 -0
  54. data/lib/sunspot/query/restriction.rb +262 -0
  55. data/lib/sunspot/query/scope.rb +9 -0
  56. data/lib/sunspot/query/sort.rb +109 -0
  57. data/lib/sunspot/query/sort_composite.rb +34 -0
  58. data/lib/sunspot/query/standard_query.rb +16 -0
  59. data/lib/sunspot/query/text_field_boost.rb +17 -0
  60. data/lib/sunspot/schema.rb +151 -0
  61. data/lib/sunspot/search.rb +9 -0
  62. data/lib/sunspot/search/abstract_search.rb +281 -0
  63. data/lib/sunspot/search/date_facet.rb +35 -0
  64. data/lib/sunspot/search/facet_row.rb +27 -0
  65. data/lib/sunspot/search/field_facet.rb +88 -0
  66. data/lib/sunspot/search/field_group.rb +32 -0
  67. data/lib/sunspot/search/group.rb +50 -0
  68. data/lib/sunspot/search/highlight.rb +38 -0
  69. data/lib/sunspot/search/hit.rb +150 -0
  70. data/lib/sunspot/search/hit_enumerable.rb +72 -0
  71. data/lib/sunspot/search/more_like_this_search.rb +31 -0
  72. data/lib/sunspot/search/paginated_collection.rb +57 -0
  73. data/lib/sunspot/search/query_facet.rb +67 -0
  74. data/lib/sunspot/search/standard_search.rb +21 -0
  75. data/lib/sunspot/session.rb +262 -0
  76. data/lib/sunspot/session_proxy.rb +95 -0
  77. data/lib/sunspot/session_proxy/abstract_session_proxy.rb +29 -0
  78. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +66 -0
  79. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +89 -0
  80. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +43 -0
  81. data/lib/sunspot/session_proxy/multicore_session_proxy.rb +67 -0
  82. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +222 -0
  83. data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +42 -0
  84. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +37 -0
  85. data/lib/sunspot/setup.rb +350 -0
  86. data/lib/sunspot/text_field_setup.rb +29 -0
  87. data/lib/sunspot/type.rb +393 -0
  88. data/lib/sunspot/util.rb +252 -0
  89. data/lib/sunspot/version.rb +3 -0
  90. data/script/console +10 -0
  91. data/spec/api/adapters_spec.rb +33 -0
  92. data/spec/api/batcher_spec.rb +112 -0
  93. data/spec/api/binding_spec.rb +50 -0
  94. data/spec/api/class_set_spec.rb +24 -0
  95. data/spec/api/hit_enumerable_spec.rb +47 -0
  96. data/spec/api/indexer/attributes_spec.rb +149 -0
  97. data/spec/api/indexer/batch_spec.rb +72 -0
  98. data/spec/api/indexer/dynamic_fields_spec.rb +42 -0
  99. data/spec/api/indexer/fixed_fields_spec.rb +57 -0
  100. data/spec/api/indexer/fulltext_spec.rb +43 -0
  101. data/spec/api/indexer/removal_spec.rb +53 -0
  102. data/spec/api/indexer/spec_helper.rb +1 -0
  103. data/spec/api/indexer_spec.rb +14 -0
  104. data/spec/api/query/advanced_manipulation_examples.rb +35 -0
  105. data/spec/api/query/connectives_examples.rb +189 -0
  106. data/spec/api/query/dsl_spec.rb +18 -0
  107. data/spec/api/query/dynamic_fields_examples.rb +165 -0
  108. data/spec/api/query/faceting_examples.rb +397 -0
  109. data/spec/api/query/fulltext_examples.rb +313 -0
  110. data/spec/api/query/function_spec.rb +79 -0
  111. data/spec/api/query/geo_examples.rb +68 -0
  112. data/spec/api/query/group_spec.rb +32 -0
  113. data/spec/api/query/highlighting_examples.rb +245 -0
  114. data/spec/api/query/more_like_this_spec.rb +140 -0
  115. data/spec/api/query/ordering_pagination_examples.rb +116 -0
  116. data/spec/api/query/scope_examples.rb +275 -0
  117. data/spec/api/query/spatial_examples.rb +27 -0
  118. data/spec/api/query/spec_helper.rb +1 -0
  119. data/spec/api/query/standard_spec.rb +29 -0
  120. data/spec/api/query/text_field_scoping_examples.rb +30 -0
  121. data/spec/api/query/types_spec.rb +20 -0
  122. data/spec/api/search/dynamic_fields_spec.rb +33 -0
  123. data/spec/api/search/faceting_spec.rb +360 -0
  124. data/spec/api/search/highlighting_spec.rb +69 -0
  125. data/spec/api/search/hits_spec.rb +131 -0
  126. data/spec/api/search/paginated_collection_spec.rb +36 -0
  127. data/spec/api/search/results_spec.rb +72 -0
  128. data/spec/api/search/search_spec.rb +23 -0
  129. data/spec/api/search/spec_helper.rb +1 -0
  130. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +85 -0
  131. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +30 -0
  132. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +41 -0
  133. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +77 -0
  134. data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +24 -0
  135. data/spec/api/session_proxy/spec_helper.rb +9 -0
  136. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +39 -0
  137. data/spec/api/session_spec.rb +232 -0
  138. data/spec/api/spec_helper.rb +3 -0
  139. data/spec/api/sunspot_spec.rb +29 -0
  140. data/spec/ext.rb +11 -0
  141. data/spec/helpers/indexer_helper.rb +17 -0
  142. data/spec/helpers/integration_helper.rb +8 -0
  143. data/spec/helpers/mock_session_helper.rb +13 -0
  144. data/spec/helpers/query_helper.rb +26 -0
  145. data/spec/helpers/search_helper.rb +68 -0
  146. data/spec/integration/dynamic_fields_spec.rb +57 -0
  147. data/spec/integration/faceting_spec.rb +251 -0
  148. data/spec/integration/field_grouping_spec.rb +66 -0
  149. data/spec/integration/geospatial_spec.rb +85 -0
  150. data/spec/integration/highlighting_spec.rb +44 -0
  151. data/spec/integration/indexing_spec.rb +55 -0
  152. data/spec/integration/keyword_search_spec.rb +317 -0
  153. data/spec/integration/local_search_spec.rb +64 -0
  154. data/spec/integration/more_like_this_spec.rb +43 -0
  155. data/spec/integration/scoped_search_spec.rb +354 -0
  156. data/spec/integration/stored_fields_spec.rb +12 -0
  157. data/spec/integration/test_pagination.rb +43 -0
  158. data/spec/integration/unicode_spec.rb +15 -0
  159. data/spec/mocks/adapters.rb +32 -0
  160. data/spec/mocks/blog.rb +3 -0
  161. data/spec/mocks/comment.rb +21 -0
  162. data/spec/mocks/connection.rb +126 -0
  163. data/spec/mocks/mock_adapter.rb +30 -0
  164. data/spec/mocks/mock_class_sharding_session_proxy.rb +24 -0
  165. data/spec/mocks/mock_record.rb +52 -0
  166. data/spec/mocks/mock_sharding_session_proxy.rb +15 -0
  167. data/spec/mocks/photo.rb +11 -0
  168. data/spec/mocks/post.rb +86 -0
  169. data/spec/mocks/super_class.rb +2 -0
  170. data/spec/mocks/user.rb +13 -0
  171. data/spec/spec_helper.rb +40 -0
  172. data/sunspot.gemspec +42 -0
  173. data/tasks/rdoc.rake +27 -0
  174. data/tasks/schema.rake +19 -0
  175. data/tasks/todo.rake +4 -0
  176. metadata +409 -0
@@ -0,0 +1,165 @@
1
+ shared_examples_for "query with dynamic field support" do
2
+ it 'restricts by dynamic string field with equality restriction' do
3
+ search do
4
+ dynamic :custom_string do
5
+ with :test, 'string'
6
+ end
7
+ end
8
+ connection.should have_last_search_including(:fq, 'custom_string\:test_ss:string')
9
+ end
10
+
11
+ it 'restricts by dynamic integer field with less than restriction' do
12
+ search do
13
+ dynamic :custom_integer do
14
+ with(:test).less_than(1)
15
+ end
16
+ end
17
+ connection.should have_last_search_including(:fq, 'custom_integer\:test_i:[* TO 1]')
18
+ end
19
+
20
+ it 'restricts by dynamic float field with between restriction' do
21
+ search do
22
+ dynamic :custom_float do
23
+ with(:test).between(2.2..3.3)
24
+ end
25
+ end
26
+ connection.should have_last_search_including(:fq, 'custom_float\:test_fm:[2\.2 TO 3\.3]')
27
+ end
28
+
29
+ it 'restricts by dynamic time field with any of restriction' do
30
+ search do
31
+ dynamic :custom_time do
32
+ with(:test).any_of([Time.parse('2009-02-10 14:00:00 UTC'),
33
+ Time.parse('2009-02-13 18:00:00 UTC')])
34
+ end
35
+ end
36
+ connection.should have_last_search_including(:fq, 'custom_time\:test_d:(2009\-02\-10T14\:00\:00Z OR 2009\-02\-13T18\:00\:00Z)')
37
+ end
38
+
39
+ it 'restricts by dynamic boolean field with equality restriction' do
40
+ search do
41
+ dynamic :custom_boolean do
42
+ with :test, false
43
+ end
44
+ end
45
+ connection.should have_last_search_including(:fq, 'custom_boolean\:test_b:false')
46
+ end
47
+
48
+ it 'negates a dynamic field restriction' do
49
+ search do
50
+ dynamic :custom_string do
51
+ without :test, 'foo'
52
+ end
53
+ end
54
+ connection.should have_last_search_including(:fq, '-custom_string\:test_ss:foo')
55
+ end
56
+
57
+ it 'scopes by a dynamic field inside a disjunction' do
58
+ search do
59
+ any_of do
60
+ dynamic :custom_string do
61
+ with :test, 'foo'
62
+ end
63
+ with :title, 'bar'
64
+ end
65
+ end
66
+ connection.should have_last_search_including(
67
+ :fq, '(custom_string\:test_ss:foo OR title_ss:bar)'
68
+ )
69
+ end
70
+
71
+ it 'orders by a dynamic field' do
72
+ search do
73
+ dynamic :custom_integer do
74
+ order_by :test, :desc
75
+ end
76
+ end
77
+ connection.should have_last_search_with(:sort => 'custom_integer:test_i desc')
78
+ end
79
+
80
+ it 'orders by a dynamic field and static field, with given precedence' do
81
+ search do
82
+ dynamic :custom_integer do
83
+ order_by :test, :desc
84
+ end
85
+ order_by :sort_title, :asc
86
+ end
87
+ connection.should have_last_search_with(:sort => 'custom_integer:test_i desc, sort_title_s asc')
88
+ end
89
+
90
+ it 'raises an UnrecognizedFieldError if an unknown dynamic field is searched by' do
91
+ lambda do
92
+ search do
93
+ dynamic(:bogus) { with :some, 'value' }
94
+ end
95
+ end.should raise_error(Sunspot::UnrecognizedFieldError)
96
+ end
97
+
98
+ it 'raises a NoMethodError if pagination is attempted in a dynamic query' do
99
+ lambda do
100
+ search do
101
+ dynamic :custom_string do
102
+ paginate :page => 3, :per_page => 10
103
+ end
104
+ end
105
+ end.should raise_error(NoMethodError)
106
+ end
107
+
108
+ it 'requests field facet on dynamic field' do
109
+ search do
110
+ dynamic :custom_string do
111
+ facet(:test)
112
+ end
113
+ end
114
+ connection.should have_last_search_including(:"facet.field", 'custom_string:test_ss')
115
+ end
116
+
117
+ it 'requests named field facet on dynamic field' do
118
+ search do
119
+ dynamic :custom_string do
120
+ facet(:test, :name => :bogus)
121
+ end
122
+ end
123
+ connection.should have_last_search_including(:"facet.field", '{!key=bogus}custom_string:test_ss')
124
+ end
125
+
126
+ it 'requests query facet with internal dynamic field' do
127
+ search do
128
+ facet :test do
129
+ row 'foo' do
130
+ dynamic :custom_string do
131
+ with :test, 'foo'
132
+ end
133
+ end
134
+ end
135
+ end
136
+ connection.should have_last_search_with(
137
+ :"facet.query" => 'custom_string\:test_ss:foo'
138
+ )
139
+ end
140
+
141
+ it 'requests query facet with external dynamic field' do
142
+ search do
143
+ dynamic :custom_string do
144
+ facet :test do
145
+ row 'foo' do
146
+ with :test, 'foo'
147
+ end
148
+ end
149
+ end
150
+ end
151
+ connection.should have_last_search_including(
152
+ :"facet.query",
153
+ 'custom_string\:test_ss:foo'
154
+ )
155
+ end
156
+
157
+ it 'allows scoping on dynamic fields common to all types' do
158
+ search Post, Namespaced::Comment do
159
+ dynamic :custom_float do
160
+ with(:test, 1.23)
161
+ end
162
+ end
163
+ connection.should have_last_search_including(:fq, 'custom_float\\:test_fm:1\\.23')
164
+ end
165
+ end
@@ -0,0 +1,397 @@
1
+ shared_examples_for "facetable query" do
2
+ describe 'on fields' do
3
+ it 'does not turn faceting on if no facet requested' do
4
+ search
5
+ connection.should_not have_last_search_with('facet')
6
+ end
7
+
8
+ it 'turns faceting on if facet is requested' do
9
+ search do
10
+ facet :category_ids
11
+ end
12
+ connection.should have_last_search_with(:facet => 'true')
13
+ end
14
+
15
+ it 'requests single field facet' do
16
+ search do
17
+ facet :category_ids
18
+ end
19
+ connection.should have_last_search_with(:"facet.field" => %w(category_ids_im))
20
+ end
21
+
22
+ it 'requests multiple field facets' do
23
+ search do
24
+ facet :category_ids, :blog_id
25
+ end
26
+ connection.should have_last_search_with(:"facet.field" => %w(category_ids_im blog_id_i))
27
+ end
28
+
29
+ it 'sets facet sort by count' do
30
+ search do
31
+ facet :category_ids, :sort => :count
32
+ end
33
+ connection.should have_last_search_with(:"f.category_ids_im.facet.sort" => 'true')
34
+ end
35
+
36
+ it 'sets facet sort by index' do
37
+ search do
38
+ facet :category_ids, :sort => :index
39
+ end
40
+ connection.should have_last_search_with(:"f.category_ids_im.facet.sort" => 'false')
41
+ end
42
+
43
+ it 'raises ArgumentError if bogus facet sort provided' do
44
+ lambda do
45
+ search do
46
+ facet :category_ids, :sort => :sideways
47
+ end
48
+ end.should raise_error(ArgumentError)
49
+ end
50
+
51
+ it 'sets the facet limit' do
52
+ search do
53
+ facet :category_ids, :limit => 10
54
+ end
55
+ connection.should have_last_search_with(:"f.category_ids_im.facet.limit" => 10)
56
+ end
57
+
58
+ it 'sets the facet minimum count' do
59
+ search do
60
+ facet :category_ids, :minimum_count => 5
61
+ end
62
+ connection.should have_last_search_with(:"f.category_ids_im.facet.mincount" => 5)
63
+ end
64
+
65
+ it 'sets the facet minimum count to zero if zeros are allowed' do
66
+ search do
67
+ facet :category_ids, :zeros => true
68
+ end
69
+ connection.should have_last_search_with(:"f.category_ids_im.facet.mincount" => 0)
70
+ end
71
+
72
+ it 'sets the facet minimum count to one by default' do
73
+ search do
74
+ facet :category_ids
75
+ end
76
+ connection.should have_last_search_with(:"f.category_ids_im.facet.mincount" => 1)
77
+ end
78
+
79
+ it 'sets the facet prefix' do
80
+ search do
81
+ facet :title, :prefix => 'Test'
82
+ end
83
+ connection.should have_last_search_with(:"f.title_ss.facet.prefix" => 'Test')
84
+ end
85
+
86
+ it 'escapes the facet prefix' do
87
+ search do
88
+ facet :title, :prefix => 'Test Title'
89
+ end
90
+ connection.should have_last_search_with(:"f.title_ss.facet.prefix" => 'Test\ Title')
91
+ end
92
+
93
+ it 'sends a query facet for :any extra' do
94
+ search do
95
+ facet :category_ids, :extra => :any
96
+ end
97
+ connection.should have_last_search_with(:"facet.query" => "category_ids_im:[* TO *]")
98
+ end
99
+
100
+ it 'sends a query facet for :none extra' do
101
+ search do
102
+ facet :category_ids, :extra => :none
103
+ end
104
+ connection.should have_last_search_with(:"facet.query" => "-category_ids_im:[* TO *]")
105
+ end
106
+
107
+ it 'raises an ArgumentError if bogus extra is passed' do
108
+ lambda do
109
+ search do
110
+ facet :category_ids, :extra => :bogus
111
+ end
112
+ end.should raise_error(ArgumentError)
113
+ end
114
+
115
+ it 'tags and excludes a scope filter in a field facet' do
116
+ search do
117
+ blog_filter = with(:blog_id, 1)
118
+ facet(:blog_id, :exclude => blog_filter)
119
+ end
120
+ filter_tag = get_filter_tag('blog_id_i:1')
121
+ connection.should have_last_search_with(
122
+ :"facet.field" => %W({!ex=#{filter_tag}}blog_id_i)
123
+ )
124
+ end
125
+
126
+ it 'tags and excludes a disjunction filter in a field facet' do
127
+ search do
128
+ blog_filter = any_of do
129
+ with(:blog_id, 1)
130
+ with(:blog_id, 2)
131
+ end
132
+ facet(:blog_id, :exclude => blog_filter)
133
+ end
134
+ filter_tag = get_filter_tag('(blog_id_i:1 OR blog_id_i:2)')
135
+ connection.should have_last_search_with(
136
+ :"facet.field" => %W({!ex=#{filter_tag}}blog_id_i)
137
+ )
138
+ end
139
+
140
+ it 'tags and excludes multiple filters in a field facet' do
141
+ search do
142
+ blog_filter = with(:blog_id, 1)
143
+ category_filter = with(:category_ids, 2)
144
+ facet(:blog_id, :exclude => [blog_filter, category_filter])
145
+ end
146
+ filter_tags = %w(blog_id_i:1 category_ids_im:2).map do |phrase|
147
+ get_filter_tag(phrase)
148
+ end.join(',')
149
+ connection.should have_last_search_with(
150
+ :"facet.field" => %W({!ex=#{filter_tags}}blog_id_i)
151
+ )
152
+ end
153
+
154
+ it 'does not tag a filter if it is not excluded' do
155
+ search do
156
+ with(:blog_id, 1)
157
+ end
158
+ connection.should have_last_search_including(:fq, "blog_id_i:1")
159
+ end
160
+
161
+ it 'names a field facet' do
162
+ search do
163
+ facet(:blog_id, :name => :blog)
164
+ end
165
+ connection.should have_last_search_including(:"facet.field", "{!key=blog}blog_id_i")
166
+ end
167
+
168
+ it 'uses the custom field facet name in facet option parameters' do
169
+ search do
170
+ facet(:blog_id, :name => :blog, :sort => :count)
171
+ end
172
+ connection.should have_last_search_with(:"f.blog.facet.sort" => 'true')
173
+ end
174
+
175
+ it 'raises an ArgumentError if exclusion attempted on a query facet' do
176
+ lambda do
177
+ search do
178
+ blog_filter = with(:blog_id, 1)
179
+ facet(:bad, :exclude => blog_filter) do
180
+ row(:bogus) { with(:blog_id, 1) }
181
+ end
182
+ end
183
+ end.should raise_error(ArgumentError)
184
+ end
185
+
186
+ it 'raises an ArgumentError if exclusion attempted on a restricted field facet' do
187
+ lambda do
188
+ search do
189
+ blog_filter = with(:blog_id, 1)
190
+ facet(:blog_id, :only => 1, :exclude => blog_filter)
191
+ end
192
+ end.should raise_error(ArgumentError)
193
+ end
194
+
195
+ it 'raises an ArgumentError if exclusion attempted on a facet with :extra' do
196
+ lambda do
197
+ search do
198
+ blog_filter = with(:blog_id, 1)
199
+ facet(:blog_id, :extra => :all, :exclude => blog_filter)
200
+ end
201
+ end.should raise_error(ArgumentError)
202
+ end
203
+ end
204
+
205
+ describe 'on time ranges' do
206
+ before :each do
207
+ @time_range = (Time.parse('2009-06-01 00:00:00 -0400')..
208
+ Time.parse('2009-07-01 00:00:00 -0400'))
209
+ end
210
+
211
+ it 'does not send date facet parameters if time range is not specified' do
212
+ search do |query|
213
+ query.facet :published_at
214
+ end
215
+ connection.should_not have_last_search_with(:"facet.date")
216
+ end
217
+
218
+ it 'sets the facet to a date facet if time range is specified' do
219
+ search do |query|
220
+ query.facet :published_at, :time_range => @time_range
221
+ end
222
+ connection.should have_last_search_with(:"facet.date" => ['published_at_dt'])
223
+ end
224
+
225
+ it 'sets the facet start and end' do
226
+ search do |query|
227
+ query.facet :published_at, :time_range => @time_range
228
+ end
229
+ connection.should have_last_search_with(
230
+ :"f.published_at_dt.facet.date.start" => '2009-06-01T04:00:00Z',
231
+ :"f.published_at_dt.facet.date.end" => '2009-07-01T04:00:00Z'
232
+ )
233
+ end
234
+
235
+ it 'defaults the time interval to 1 day' do
236
+ search do |query|
237
+ query.facet :published_at, :time_range => @time_range
238
+ end
239
+ connection.should have_last_search_with(:"f.published_at_dt.facet.date.gap" => "+86400SECONDS")
240
+ end
241
+
242
+ it 'uses custom time interval' do
243
+ search do |query|
244
+ query.facet :published_at, :time_range => @time_range, :time_interval => 3600
245
+ end
246
+ connection.should have_last_search_with(:"f.published_at_dt.facet.date.gap" => "+3600SECONDS")
247
+ end
248
+
249
+ it 'does not allow date faceting on a non-date field' do
250
+ lambda do
251
+ search do |query|
252
+ query.facet :blog_id, :time_range => @time_range
253
+ end
254
+ end.should raise_error(ArgumentError)
255
+ end
256
+ end
257
+
258
+ describe 'using queries' do
259
+ it 'turns faceting on' do
260
+ search do
261
+ facet :foo do
262
+ row :bar do
263
+ with(:average_rating).between(4.0..5.0)
264
+ end
265
+ end
266
+ end
267
+ connection.should have_last_search_with(:facet => 'true')
268
+ end
269
+
270
+ it 'facets by query' do
271
+ search do
272
+ facet :foo do
273
+ row :bar do
274
+ with(:average_rating).between(4.0..5.0)
275
+ end
276
+ end
277
+ end
278
+ connection.should have_last_search_with(:"facet.query" => 'average_rating_ft:[4\.0 TO 5\.0]')
279
+ end
280
+
281
+ it 'requests multiple query facets' do
282
+ search do
283
+ facet :foo do
284
+ row :bar do
285
+ with(:average_rating).between(3.0..4.0)
286
+ end
287
+ row :baz do
288
+ with(:average_rating).between(4.0..5.0)
289
+ end
290
+ end
291
+ end
292
+ connection.should have_last_search_with(
293
+ :"facet.query" => [
294
+ 'average_rating_ft:[3\.0 TO 4\.0]',
295
+ 'average_rating_ft:[4\.0 TO 5\.0]'
296
+ ]
297
+ )
298
+ end
299
+
300
+ it 'requests query facet with multiple conditions' do
301
+ search do
302
+ facet :foo do
303
+ row :bar do
304
+ with(:category_ids, 1)
305
+ with(:blog_id, 2)
306
+ end
307
+ end
308
+ end
309
+ connection.should have_last_search_with(
310
+ :"facet.query" => '(category_ids_im:1 AND blog_id_i:2)'
311
+ )
312
+ end
313
+
314
+ it 'requests query facet with disjunction' do
315
+ search do
316
+ facet :foo do
317
+ row :bar do
318
+ any_of do
319
+ with(:category_ids, 1)
320
+ with(:blog_id, 2)
321
+ end
322
+ end
323
+ end
324
+ end
325
+ connection.should have_last_search_with(
326
+ :"facet.query" => '(category_ids_im:1 OR blog_id_i:2)'
327
+ )
328
+ end
329
+
330
+ it 'builds query facets when passed :only argument to field facet declaration' do
331
+ search do
332
+ facet :category_ids, :only => [1, 3]
333
+ end
334
+ connection.should have_last_search_with(
335
+ :"facet.query" => ['category_ids_im:1', 'category_ids_im:3']
336
+ )
337
+ end
338
+
339
+ it 'converts limited query facet values to the correct type' do
340
+ search do
341
+ facet :published_at, :only => [Time.utc(2009, 8, 28, 15, 33), Time.utc(2008,8, 28, 15, 33)]
342
+ end
343
+ connection.should have_last_search_with(
344
+ :"facet.query" => [
345
+ 'published_at_dt:2009\-08\-28T15\:33\:00Z',
346
+ 'published_at_dt:2008\-08\-28T15\:33\:00Z'
347
+ ]
348
+ )
349
+ end
350
+
351
+ it 'ignores facet query with no rows' do
352
+ search do
353
+ facet(:foo) {}
354
+ end
355
+ connection.should_not have_last_search_with(:"facet.query")
356
+ end
357
+
358
+ it 'ignores facet query row with no restrictions' do
359
+ search do
360
+ facet :foo do
361
+ row(:bar) do
362
+ with(:blog_id, 1)
363
+ end
364
+ row(:baz) {}
365
+ end
366
+ end
367
+ connection.searches.last[:"facet.query"].should be_a(String)
368
+ end
369
+
370
+ it 'ignores facet query with only empty rows' do
371
+ search do
372
+ facet :foo do
373
+ row(:bar) {}
374
+ end
375
+ end
376
+ connection.should_not have_last_search_with(:"facet.query")
377
+ end
378
+
379
+ it 'does not allow 0 arguments to facet method with block' do
380
+ lambda do
381
+ search do
382
+ facet do
383
+ end
384
+ end
385
+ end.should raise_error(ArgumentError)
386
+ end
387
+
388
+ it 'does not allow more than 1 argument to facet method with block' do
389
+ lambda do
390
+ search do
391
+ facet :foo, :bar do
392
+ end
393
+ end
394
+ end.should raise_error(ArgumentError)
395
+ end
396
+ end
397
+ end