sunspot_rbg 1.3.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 (222) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +4 -0
  3. data/History.txt +222 -0
  4. data/LICENSE +18 -0
  5. data/Rakefile +17 -0
  6. data/TODO +13 -0
  7. data/VERSION.yml +4 -0
  8. data/bin/sunspot-installer +19 -0
  9. data/bin/sunspot-solr +74 -0
  10. data/installer/config/schema.yml +95 -0
  11. data/lib/light_config.rb +40 -0
  12. data/lib/sunspot/adapters.rb +265 -0
  13. data/lib/sunspot/composite_setup.rb +202 -0
  14. data/lib/sunspot/configuration.rb +46 -0
  15. data/lib/sunspot/data_extractor.rb +50 -0
  16. data/lib/sunspot/dsl/adjustable.rb +47 -0
  17. data/lib/sunspot/dsl/field_query.rb +279 -0
  18. data/lib/sunspot/dsl/fields.rb +103 -0
  19. data/lib/sunspot/dsl/fulltext.rb +243 -0
  20. data/lib/sunspot/dsl/function.rb +14 -0
  21. data/lib/sunspot/dsl/functional.rb +44 -0
  22. data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
  23. data/lib/sunspot/dsl/paginatable.rb +28 -0
  24. data/lib/sunspot/dsl/query_facet.rb +36 -0
  25. data/lib/sunspot/dsl/restriction.rb +25 -0
  26. data/lib/sunspot/dsl/restriction_with_near.rb +121 -0
  27. data/lib/sunspot/dsl/scope.rb +217 -0
  28. data/lib/sunspot/dsl/search.rb +30 -0
  29. data/lib/sunspot/dsl/standard_query.rb +121 -0
  30. data/lib/sunspot/dsl.rb +5 -0
  31. data/lib/sunspot/field.rb +193 -0
  32. data/lib/sunspot/field_factory.rb +129 -0
  33. data/lib/sunspot/indexer.rb +131 -0
  34. data/lib/sunspot/installer/library_installer.rb +45 -0
  35. data/lib/sunspot/installer/schema_builder.rb +219 -0
  36. data/lib/sunspot/installer/solrconfig_updater.rb +76 -0
  37. data/lib/sunspot/installer/task_helper.rb +18 -0
  38. data/lib/sunspot/installer.rb +31 -0
  39. data/lib/sunspot/query/abstract_field_facet.rb +52 -0
  40. data/lib/sunspot/query/boost_query.rb +24 -0
  41. data/lib/sunspot/query/common_query.rb +85 -0
  42. data/lib/sunspot/query/composite_fulltext.rb +36 -0
  43. data/lib/sunspot/query/connective.rb +206 -0
  44. data/lib/sunspot/query/date_field_facet.rb +14 -0
  45. data/lib/sunspot/query/dismax.rb +128 -0
  46. data/lib/sunspot/query/field_facet.rb +41 -0
  47. data/lib/sunspot/query/filter.rb +38 -0
  48. data/lib/sunspot/query/function_query.rb +52 -0
  49. data/lib/sunspot/query/geo.rb +53 -0
  50. data/lib/sunspot/query/highlighting.rb +55 -0
  51. data/lib/sunspot/query/more_like_this.rb +61 -0
  52. data/lib/sunspot/query/more_like_this_query.rb +12 -0
  53. data/lib/sunspot/query/pagination.rb +38 -0
  54. data/lib/sunspot/query/query_facet.rb +16 -0
  55. data/lib/sunspot/query/restriction.rb +262 -0
  56. data/lib/sunspot/query/scope.rb +9 -0
  57. data/lib/sunspot/query/sort.rb +95 -0
  58. data/lib/sunspot/query/sort_composite.rb +33 -0
  59. data/lib/sunspot/query/standard_query.rb +16 -0
  60. data/lib/sunspot/query/text_field_boost.rb +17 -0
  61. data/lib/sunspot/query.rb +11 -0
  62. data/lib/sunspot/schema.rb +151 -0
  63. data/lib/sunspot/search/abstract_search.rb +293 -0
  64. data/lib/sunspot/search/date_facet.rb +35 -0
  65. data/lib/sunspot/search/facet_row.rb +27 -0
  66. data/lib/sunspot/search/field_facet.rb +88 -0
  67. data/lib/sunspot/search/highlight.rb +38 -0
  68. data/lib/sunspot/search/hit.rb +136 -0
  69. data/lib/sunspot/search/more_like_this_search.rb +31 -0
  70. data/lib/sunspot/search/paginated_collection.rb +55 -0
  71. data/lib/sunspot/search/query_facet.rb +67 -0
  72. data/lib/sunspot/search/standard_search.rb +21 -0
  73. data/lib/sunspot/search.rb +9 -0
  74. data/lib/sunspot/server.rb +152 -0
  75. data/lib/sunspot/session.rb +260 -0
  76. data/lib/sunspot/session_proxy/abstract_session_proxy.rb +29 -0
  77. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +66 -0
  78. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +89 -0
  79. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +43 -0
  80. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +222 -0
  81. data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +42 -0
  82. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +37 -0
  83. data/lib/sunspot/session_proxy.rb +87 -0
  84. data/lib/sunspot/setup.rb +350 -0
  85. data/lib/sunspot/text_field_setup.rb +29 -0
  86. data/lib/sunspot/type.rb +372 -0
  87. data/lib/sunspot/util.rb +243 -0
  88. data/lib/sunspot/version.rb +3 -0
  89. data/lib/sunspot.rb +569 -0
  90. data/lib/sunspot_rbg.rb +7 -0
  91. data/log/.gitignore +1 -0
  92. data/pkg/.gitignore +1 -0
  93. data/script/console +10 -0
  94. data/solr/README.txt +42 -0
  95. data/solr/etc/jetty.xml +218 -0
  96. data/solr/etc/webdefault.xml +379 -0
  97. data/solr/lib/jetty-6.1.3.jar +0 -0
  98. data/solr/lib/jetty-util-6.1.3.jar +0 -0
  99. data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  100. data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
  101. data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
  102. data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  103. data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
  104. data/solr/logs/.gitignore +1 -0
  105. data/solr/solr/.gitignore +1 -0
  106. data/solr/solr/README.txt +54 -0
  107. data/solr/solr/conf/admin-extra.html +31 -0
  108. data/solr/solr/conf/elevate.xml +36 -0
  109. data/solr/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  110. data/solr/solr/conf/protwords.txt +21 -0
  111. data/solr/solr/conf/schema.xml +238 -0
  112. data/solr/solr/conf/scripts.conf +24 -0
  113. data/solr/solr/conf/solrconfig.xml +934 -0
  114. data/solr/solr/conf/spellings.txt +2 -0
  115. data/solr/solr/conf/stopwords.txt +58 -0
  116. data/solr/solr/conf/synonyms.txt +31 -0
  117. data/solr/solr/conf/xslt/example.xsl +132 -0
  118. data/solr/solr/conf/xslt/example_atom.xsl +67 -0
  119. data/solr/solr/conf/xslt/example_rss.xsl +66 -0
  120. data/solr/solr/conf/xslt/luke.xsl +337 -0
  121. data/solr/start.jar +0 -0
  122. data/solr/webapps/solr.war +0 -0
  123. data/solr-1.3/etc/jetty.xml +212 -0
  124. data/solr-1.3/etc/webdefault.xml +379 -0
  125. data/solr-1.3/lib/jetty-6.1.3.jar +0 -0
  126. data/solr-1.3/lib/jetty-util-6.1.3.jar +0 -0
  127. data/solr-1.3/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  128. data/solr-1.3/lib/jsp-2.1/core-3.1.1.jar +0 -0
  129. data/solr-1.3/lib/jsp-2.1/jsp-2.1.jar +0 -0
  130. data/solr-1.3/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  131. data/solr-1.3/lib/servlet-api-2.5-6.1.3.jar +0 -0
  132. data/solr-1.3/solr/conf/elevate.xml +36 -0
  133. data/solr-1.3/solr/conf/protwords.txt +21 -0
  134. data/solr-1.3/solr/conf/schema.xml +64 -0
  135. data/solr-1.3/solr/conf/solrconfig.xml +725 -0
  136. data/solr-1.3/solr/conf/stopwords.txt +57 -0
  137. data/solr-1.3/solr/conf/synonyms.txt +31 -0
  138. data/solr-1.3/solr/lib/geoapi-nogenerics-2.1-M2.jar +0 -0
  139. data/solr-1.3/solr/lib/gt2-referencing-2.3.1.jar +0 -0
  140. data/solr-1.3/solr/lib/jsr108-0.01.jar +0 -0
  141. data/solr-1.3/solr/lib/locallucene.jar +0 -0
  142. data/solr-1.3/solr/lib/localsolr.jar +0 -0
  143. data/solr-1.3/start.jar +0 -0
  144. data/solr-1.3/webapps/solr.war +0 -0
  145. data/spec/api/adapters_spec.rb +33 -0
  146. data/spec/api/binding_spec.rb +50 -0
  147. data/spec/api/indexer/attributes_spec.rb +149 -0
  148. data/spec/api/indexer/batch_spec.rb +46 -0
  149. data/spec/api/indexer/dynamic_fields_spec.rb +42 -0
  150. data/spec/api/indexer/fixed_fields_spec.rb +57 -0
  151. data/spec/api/indexer/fulltext_spec.rb +43 -0
  152. data/spec/api/indexer/removal_spec.rb +53 -0
  153. data/spec/api/indexer/spec_helper.rb +1 -0
  154. data/spec/api/indexer_spec.rb +14 -0
  155. data/spec/api/query/advanced_manipulation_examples.rb +35 -0
  156. data/spec/api/query/connectives_examples.rb +189 -0
  157. data/spec/api/query/dsl_spec.rb +18 -0
  158. data/spec/api/query/dynamic_fields_examples.rb +165 -0
  159. data/spec/api/query/faceting_examples.rb +397 -0
  160. data/spec/api/query/fulltext_examples.rb +313 -0
  161. data/spec/api/query/function_spec.rb +70 -0
  162. data/spec/api/query/geo_examples.rb +68 -0
  163. data/spec/api/query/highlighting_examples.rb +223 -0
  164. data/spec/api/query/more_like_this_spec.rb +140 -0
  165. data/spec/api/query/ordering_pagination_examples.rb +95 -0
  166. data/spec/api/query/scope_examples.rb +275 -0
  167. data/spec/api/query/spec_helper.rb +1 -0
  168. data/spec/api/query/standard_spec.rb +28 -0
  169. data/spec/api/query/text_field_scoping_examples.rb +30 -0
  170. data/spec/api/query/types_spec.rb +20 -0
  171. data/spec/api/search/dynamic_fields_spec.rb +33 -0
  172. data/spec/api/search/faceting_spec.rb +360 -0
  173. data/spec/api/search/highlighting_spec.rb +69 -0
  174. data/spec/api/search/hits_spec.rb +120 -0
  175. data/spec/api/search/paginated_collection_spec.rb +26 -0
  176. data/spec/api/search/results_spec.rb +66 -0
  177. data/spec/api/search/search_spec.rb +23 -0
  178. data/spec/api/search/spec_helper.rb +1 -0
  179. data/spec/api/server_spec.rb +91 -0
  180. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +85 -0
  181. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +30 -0
  182. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +41 -0
  183. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +77 -0
  184. data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +24 -0
  185. data/spec/api/session_proxy/spec_helper.rb +9 -0
  186. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +50 -0
  187. data/spec/api/session_spec.rb +220 -0
  188. data/spec/api/spec_helper.rb +3 -0
  189. data/spec/api/sunspot_spec.rb +18 -0
  190. data/spec/ext.rb +11 -0
  191. data/spec/helpers/indexer_helper.rb +29 -0
  192. data/spec/helpers/query_helper.rb +38 -0
  193. data/spec/helpers/search_helper.rb +80 -0
  194. data/spec/integration/dynamic_fields_spec.rb +55 -0
  195. data/spec/integration/faceting_spec.rb +238 -0
  196. data/spec/integration/highlighting_spec.rb +22 -0
  197. data/spec/integration/indexing_spec.rb +33 -0
  198. data/spec/integration/keyword_search_spec.rb +317 -0
  199. data/spec/integration/local_search_spec.rb +64 -0
  200. data/spec/integration/more_like_this_spec.rb +43 -0
  201. data/spec/integration/scoped_search_spec.rb +354 -0
  202. data/spec/integration/spec_helper.rb +7 -0
  203. data/spec/integration/stored_fields_spec.rb +10 -0
  204. data/spec/integration/test_pagination.rb +32 -0
  205. data/spec/mocks/adapters.rb +32 -0
  206. data/spec/mocks/blog.rb +3 -0
  207. data/spec/mocks/comment.rb +21 -0
  208. data/spec/mocks/connection.rb +126 -0
  209. data/spec/mocks/mock_adapter.rb +30 -0
  210. data/spec/mocks/mock_class_sharding_session_proxy.rb +24 -0
  211. data/spec/mocks/mock_record.rb +52 -0
  212. data/spec/mocks/mock_sharding_session_proxy.rb +15 -0
  213. data/spec/mocks/photo.rb +11 -0
  214. data/spec/mocks/post.rb +85 -0
  215. data/spec/mocks/super_class.rb +2 -0
  216. data/spec/mocks/user.rb +13 -0
  217. data/spec/spec_helper.rb +30 -0
  218. data/sunspot.gemspec +40 -0
  219. data/tasks/rdoc.rake +27 -0
  220. data/tasks/schema.rake +19 -0
  221. data/tasks/todo.rake +4 -0
  222. metadata +457 -0
@@ -0,0 +1,70 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ describe 'function query' do
4
+ it "should send query to solr with boost function" do
5
+ session.search Post do
6
+ keywords('pizza') do
7
+ boost(function { :average_rating })
8
+ end
9
+ end
10
+ connection.should have_last_search_including(:bf, 'average_rating_ft')
11
+ end
12
+
13
+ it "should handle boost function with constant float" do
14
+ session.search Post do
15
+ keywords('pizza') do
16
+ boost(function { 10.5 })
17
+ end
18
+ end
19
+ connection.should have_last_search_including(:bf, '10.5')
20
+ end
21
+
22
+ it "should handle boost function with time literal" do
23
+ session.search Post do
24
+ keywords('pizza') do
25
+ boost(function { Time.parse('2010-03-25 14:13:00 EDT') })
26
+ end
27
+ end
28
+ connection.should have_last_search_including(:bf, '2010-03-25T18:13:00Z')
29
+ end
30
+
31
+ it "should handle arbitrary functions in a function query block" do
32
+ session.search Post do
33
+ keywords('pizza') do
34
+ boost(function { product(:average_rating, 10) })
35
+ end
36
+ end
37
+ connection.should have_last_search_including(:bf, 'product(average_rating_ft,10)')
38
+ end
39
+
40
+ it "should handle nested functions in a function query block" do
41
+ session.search Post do
42
+ keywords('pizza') do
43
+ boost(function { product(:average_rating, sum(:average_rating, 20)) })
44
+ end
45
+ end
46
+ connection.should have_last_search_including(:bf, 'product(average_rating_ft,sum(average_rating_ft,20))')
47
+ end
48
+
49
+ # TODO SOLR 1.5
50
+ it "should raise ArgumentError if string literal passed" do
51
+ lambda do
52
+ session.search Post do
53
+ keywords('pizza') do
54
+ boost(function { "hello world" })
55
+ end
56
+ end
57
+ end.should raise_error(ArgumentError)
58
+ end
59
+
60
+ it "should raise UnrecognizedFieldError if bogus field name passed" do
61
+ lambda do
62
+ session.search Post do
63
+ keywords('pizza') do
64
+ boost(function { :bogus })
65
+ end
66
+ end
67
+ end.should raise_error(Sunspot::UnrecognizedFieldError)
68
+ end
69
+ end
70
+
@@ -0,0 +1,68 @@
1
+ require 'bigdecimal'
2
+
3
+ shared_examples_for 'geohash query' do
4
+ it 'searches for nearby points with defaults' do
5
+ search do
6
+ with(:coordinates).near(40.7, -73.5)
7
+ end
8
+ connection.should have_last_search_including(:q, build_geo_query)
9
+ end
10
+
11
+ it 'searches for nearby points with non-Float arguments' do
12
+ search do
13
+ with(:coordinates).near(BigDecimal.new('40.7'), BigDecimal.new('-73.5'))
14
+ end
15
+ connection.should have_last_search_including(:q, build_geo_query)
16
+ end
17
+
18
+ it 'searches for nearby points with given precision' do
19
+ search do
20
+ with(:coordinates).near(40.7, -73.5, :precision => 10)
21
+ end
22
+ connection.should have_last_search_including(:q, build_geo_query(:precision => 10))
23
+ end
24
+
25
+ it 'searches for nearby points with given precision factor' do
26
+ search do
27
+ with(:coordinates).near(40.7, -73.5, :precision_factor => 1.5)
28
+ end
29
+ connection.should have_last_search_including(:q, build_geo_query(:precision_factor => 1.5))
30
+ end
31
+
32
+ it 'searches for nearby points with given boost' do
33
+ search do
34
+ with(:coordinates).near(40.7, -73.5, :boost => 2.0)
35
+ end
36
+ connection.should have_last_search_including(:q, build_geo_query(:boost => 2.0))
37
+ end
38
+
39
+ it 'performs both dismax search and location search' do
40
+ search do
41
+ fulltext 'pizza', :fields => :title
42
+ with(:coordinates).near(40.7, -73.5)
43
+ end
44
+ expected =
45
+ "{!dismax fl='* score' qf='title_text'}pizza (#{build_geo_query})"
46
+ connection.should have_last_search_including(
47
+ :q,
48
+ %Q(_query_:"{!dismax qf='title_text'}pizza" (#{build_geo_query}))
49
+ )
50
+ end
51
+
52
+ private
53
+
54
+ def build_geo_query(options = {})
55
+ precision = options[:precision] || 7
56
+ precision_factor = options[:precision_factor] || 16.0
57
+ boost = options[:boost] || 1.0
58
+ hash = 'dr5xx3nytvgs'
59
+ (precision..12).map do |i|
60
+ phrase =
61
+ if i == 12 then hash
62
+ else "#{hash[0, i]}*"
63
+ end
64
+ precision_boost = Sunspot::Util.format_float(boost*precision_factor**(i-12.0), 3)
65
+ "coordinates_s:#{phrase}^#{precision_boost}"
66
+ end.reverse.join(' OR ')
67
+ end
68
+ end
@@ -0,0 +1,223 @@
1
+ shared_examples_for "query with highlighting support" do
2
+ it 'should not send highlight parameter when highlight not requested' do
3
+ search do
4
+ keywords 'test'
5
+ end
6
+ connection.should_not have_last_search_with(:hl)
7
+ end
8
+
9
+ it 'should enable highlighting when highlighting requested as keywords argument' do
10
+ search do
11
+ keywords 'test', :highlight => true
12
+ end
13
+ connection.should have_last_search_with(:hl => 'on')
14
+ end
15
+
16
+ it 'should not set highlight fields parameter if highlight fields are not passed' do
17
+ search do
18
+ keywords 'test', :highlight => true, :fields => [:title]
19
+ end
20
+ connection.should_not have_last_search_with(:'hl.fl')
21
+ end
22
+
23
+ it 'should enable highlighting on multiple fields when highlighting requested as array of fields via keywords argument' do
24
+ search do
25
+ keywords 'test', :highlight => [:title, :body]
26
+ end
27
+
28
+ connection.should have_last_search_with(:hl => 'on', :'hl.fl' => %w(title_text body_textsv))
29
+ end
30
+
31
+ it 'should raise UnrecognizedFieldError if try to highlight unexisting field via keywords argument' do
32
+ lambda {
33
+ search do
34
+ keywords 'test', :highlight => [:unknown_field]
35
+ end
36
+ }.should raise_error(Sunspot::UnrecognizedFieldError)
37
+ end
38
+
39
+ it 'should enable highlighting on multiple fields when highlighting requested as list of fields via block call' do
40
+ search do
41
+ keywords 'test' do
42
+ highlight :title, :body
43
+ end
44
+ end
45
+
46
+ connection.should have_last_search_with(:hl => 'on', :'hl.fl' => %w(title_text body_textsv))
47
+ end
48
+
49
+ it 'should enable highlighting on multiple fields for multiple search types' do
50
+ session.search(Post, Namespaced::Comment) do
51
+ keywords 'test' do
52
+ highlight :body
53
+ end
54
+ end
55
+ connection.searches.last[:'hl.fl'].to_set.should == Set['body_text', 'body_textsv']
56
+ end
57
+
58
+ it 'should raise UnrecognizedFieldError if try to highlight unexisting field via block call' do
59
+ lambda {
60
+ search do
61
+ keywords 'test' do
62
+ highlight :unknown_field
63
+ end
64
+ end
65
+ }.should raise_error(Sunspot::UnrecognizedFieldError)
66
+ end
67
+
68
+ it 'should set internal formatting' do
69
+ search do
70
+ keywords 'test', :highlight => true
71
+ end
72
+ connection.should have_last_search_with(
73
+ :"hl.simple.pre" => '@@@hl@@@',
74
+ :"hl.simple.post" => '@@@endhl@@@'
75
+ )
76
+ end
77
+
78
+ it 'should set highlight fields from DSL' do
79
+ search do
80
+ keywords 'test' do
81
+ highlight :title
82
+ end
83
+ end
84
+ connection.should have_last_search_with(
85
+ :"hl.fl" => %w(title_text)
86
+ )
87
+ end
88
+
89
+ it 'should not set formatting params specific to fields if fields specified' do
90
+ search do
91
+ keywords 'test', :highlight => :body
92
+ end
93
+ connection.should have_last_search_with(
94
+ :"hl.simple.pre" => '@@@hl@@@',
95
+ :"hl.simple.post" => '@@@endhl@@@'
96
+ )
97
+ end
98
+
99
+ it 'should set maximum highlights per field' do
100
+ search do
101
+ keywords 'test' do
102
+ highlight :max_snippets => 3
103
+ end
104
+ end
105
+ connection.should have_last_search_with(
106
+ :"hl.snippets" => 3
107
+ )
108
+ end
109
+
110
+ it 'should set max snippets specific to highlight fields' do
111
+ search do
112
+ keywords 'test' do
113
+ highlight :title, :max_snippets => 3
114
+ end
115
+ end
116
+ connection.should have_last_search_with(
117
+ :"hl.fl" => %w(title_text),
118
+ :"f.title_text.hl.snippets" => 3
119
+ )
120
+ end
121
+
122
+ it 'should set the maximum size' do
123
+ search do
124
+ keywords 'text' do
125
+ highlight :fragment_size => 200
126
+ end
127
+ end
128
+ connection.should have_last_search_with(
129
+ :"hl.fragsize" => 200
130
+ )
131
+ end
132
+
133
+ it 'should set the maximum size for specific fields' do
134
+ search do
135
+ keywords 'text' do
136
+ highlight :title, :fragment_size => 200
137
+ end
138
+ end
139
+ connection.should have_last_search_with(
140
+ :"f.title_text.hl.fragsize" => 200
141
+ )
142
+ end
143
+
144
+ it 'enables merging of contiguous fragments' do
145
+ search do
146
+ keywords 'test' do
147
+ highlight :merge_contiguous_fragments => true
148
+ end
149
+ end
150
+ connection.should have_last_search_with(
151
+ :"hl.mergeContiguous" => 'true'
152
+ )
153
+ end
154
+
155
+ it 'enables merging of contiguous fragments for specific fields' do
156
+ search do
157
+ keywords 'test' do
158
+ highlight :title, :merge_contiguous_fragments => true
159
+ end
160
+ end
161
+ connection.should have_last_search_with(
162
+ :"f.title_text.hl.mergeContiguous" => 'true'
163
+ )
164
+ end
165
+
166
+ it 'enables use of phrase highlighter' do
167
+ search do
168
+ keywords 'test' do
169
+ highlight :phrase_highlighter => true
170
+ end
171
+ end
172
+ connection.should have_last_search_with(
173
+ :"hl.usePhraseHighlighter" => 'true'
174
+ )
175
+ end
176
+
177
+ it 'enables use of phrase highlighter for specific fields' do
178
+ search do
179
+ keywords 'test' do
180
+ highlight :title, :phrase_highlighter => true
181
+ end
182
+ end
183
+ connection.should have_last_search_with(
184
+ :"f.title_text.hl.usePhraseHighlighter" => 'true'
185
+ )
186
+ end
187
+
188
+ it 'requires field match if requested' do
189
+ search do
190
+ keywords 'test' do
191
+ highlight :phrase_highlighter => true, :require_field_match => true
192
+ end
193
+ end
194
+ connection.should have_last_search_with(
195
+ :"hl.requireFieldMatch" => 'true'
196
+ )
197
+ end
198
+
199
+ it 'requires field match for specified field if requested' do
200
+ search do
201
+ keywords 'test' do
202
+ highlight :title, :phrase_highlighter => true, :require_field_match => true
203
+ end
204
+ end
205
+ connection.should have_last_search_with(
206
+ :"f.title_text.hl.requireFieldMatch" => 'true'
207
+ )
208
+ end
209
+
210
+ it 'sets field specific params for different fields if different params given' do
211
+ search do
212
+ keywords 'test' do
213
+ highlight :title, :max_snippets => 2
214
+ highlight :body, :max_snippets => 1
215
+ end
216
+ end
217
+ connection.should have_last_search_with(
218
+ :"hl.fl" => %w(title_text body_textsv),
219
+ :"f.title_text.hl.snippets" => 2,
220
+ :"f.body_textsv.hl.snippets" => 1
221
+ )
222
+ end
223
+ end
@@ -0,0 +1,140 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ describe 'more_like_this' do
4
+ before :each do
5
+ connection.expected_handler = :mlt
6
+ end
7
+
8
+ it_should_behave_like "scoped query"
9
+ it_should_behave_like "facetable query"
10
+ it_should_behave_like "query with advanced manipulation"
11
+ it_should_behave_like "query with connective scope"
12
+ it_should_behave_like "query with dynamic field support"
13
+ it_should_behave_like "sortable query"
14
+ it_should_behave_like "query with text field scoping"
15
+
16
+ it 'should query passed in object' do
17
+ p = Post.new
18
+ session.more_like_this(p)
19
+ connection.should have_last_search_with(:q => "id:Post\\ #{p.id}")
20
+ end
21
+
22
+ it 'should use more_like_this fields if no fields specified' do
23
+ session.more_like_this(Post.new)
24
+ connection.searches.last[:"mlt.fl"].split(',').sort.should == %w(body_textsv tags_textv)
25
+ end
26
+
27
+ it 'should use more_like_this fields if specified' do
28
+ session.more_like_this(Post.new) do
29
+ fields :body
30
+ end
31
+ connection.should have_last_search_with(:"mlt.fl" => "body_textsv")
32
+ end
33
+
34
+ it 'assigns boosts to fields when specified' do
35
+ session.more_like_this(Post.new) do
36
+ fields :body, :tags => 8
37
+ end
38
+ connection.searches.last[:"mlt.fl"].split(',').sort.should == %w(body_textsv tags_textv)
39
+ connection.should have_last_search_with(:qf => "tags_textv^8")
40
+ end
41
+
42
+ it 'doesn\'t assign boosts to fields when not specified' do
43
+ session.more_like_this(Post.new) do
44
+ fields :body
45
+ end
46
+ connection.should_not have_last_search_with(:qf)
47
+ end
48
+
49
+ it 'should raise ArgumentError if a field is not setup for more_like_this' do
50
+ lambda do
51
+ session.more_like_this(Post.new) do
52
+ fields :title
53
+ end
54
+ end.should raise_error(ArgumentError)
55
+ end
56
+
57
+ it 'should accept options' do
58
+ session.more_like_this(Post.new) do
59
+ minimum_term_frequency 1
60
+ minimum_document_frequency 2
61
+ minimum_word_length 3
62
+ maximum_word_length 4
63
+ maximum_query_terms 5
64
+ boost_by_relevance false
65
+ end
66
+ connection.should have_last_search_with(:"mlt.mintf" => 1)
67
+ connection.should have_last_search_with(:"mlt.mindf" => 2)
68
+ connection.should have_last_search_with(:"mlt.minwl" => 3)
69
+ connection.should have_last_search_with(:"mlt.maxwl" => 4)
70
+ connection.should have_last_search_with(:"mlt.maxqt" => 5)
71
+ connection.should have_last_search_with(:"mlt.boost" => false)
72
+ end
73
+
74
+ it 'should accept short options' do
75
+ session.more_like_this(Post.new) do
76
+ mintf 1
77
+ mindf 2
78
+ minwl 3
79
+ maxwl 4
80
+ maxqt 5
81
+ boost true
82
+ end
83
+ connection.should have_last_search_with(:"mlt.mintf" => 1)
84
+ connection.should have_last_search_with(:"mlt.mindf" => 2)
85
+ connection.should have_last_search_with(:"mlt.minwl" => 3)
86
+ connection.should have_last_search_with(:"mlt.maxwl" => 4)
87
+ connection.should have_last_search_with(:"mlt.maxqt" => 5)
88
+ connection.should have_last_search_with(:"mlt.boost" => true)
89
+ end
90
+
91
+ it 'paginates using default per_page when page not provided' do
92
+ session.more_like_this(Post.new)
93
+ connection.should have_last_search_with(:rows => 30)
94
+ end
95
+
96
+ it 'paginates using default per_page when page provided' do
97
+ session.more_like_this(Post.new) do
98
+ paginate :page => 2
99
+ end
100
+ connection.should have_last_search_with(:rows => 30, :start => 30)
101
+ end
102
+
103
+ it 'paginates using provided per_page' do
104
+ session.more_like_this(Post.new) do
105
+ paginate :page => 4, :per_page => 15
106
+ end
107
+ connection.should have_last_search_with(:rows => 15, :start => 45)
108
+ end
109
+
110
+ it 'defaults to page 1 if no :page argument given' do
111
+ session.more_like_this(Post.new) do
112
+ paginate :per_page => 15
113
+ end
114
+ connection.should have_last_search_with(:rows => 15, :start => 0)
115
+ end
116
+
117
+ it 'paginates from string argument' do
118
+ session.more_like_this(Post.new) do
119
+ paginate :page => '3', :per_page => '15'
120
+ end
121
+ connection.should have_last_search_with(:rows => 15, :start => 30)
122
+ end
123
+
124
+ it "should send query to solr with adjusted parameters (keyword example)" do
125
+ session.more_like_this(Post.new) do
126
+ adjust_solr_params do |params|
127
+ params[:q] = 'new search'
128
+ params[:some] = 'param'
129
+ end
130
+ end
131
+ connection.should have_last_search_with(:q => 'new search')
132
+ connection.should have_last_search_with(:some => 'param')
133
+ end
134
+
135
+ private
136
+
137
+ def search(*args, &block)
138
+ session.more_like_this(Post.new, *args, &block)
139
+ end
140
+ end
@@ -0,0 +1,95 @@
1
+ shared_examples_for 'sortable query' do
2
+ it 'paginates using default per_page when page not provided' do
3
+ search
4
+ connection.should have_last_search_with(:rows => 30)
5
+ end
6
+
7
+ it 'paginates using default per_page when page provided' do
8
+ search do
9
+ paginate :page => 2
10
+ end
11
+ connection.should have_last_search_with(:rows => 30, :start => 30)
12
+ end
13
+
14
+ it 'paginates using provided per_page' do
15
+ search do
16
+ paginate :page => 4, :per_page => 15
17
+ end
18
+ connection.should have_last_search_with(:rows => 15, :start => 45)
19
+ end
20
+
21
+ it 'defaults to page 1 if no :page argument given' do
22
+ search do
23
+ paginate :per_page => 15
24
+ end
25
+ connection.should have_last_search_with(:rows => 15, :start => 0)
26
+ end
27
+
28
+ it 'paginates from string argument' do
29
+ search do
30
+ paginate :page => '3', :per_page => '15'
31
+ end
32
+ connection.should have_last_search_with(:rows => 15, :start => 30)
33
+ end
34
+
35
+ it 'orders by a single field' do
36
+ search do
37
+ order_by :average_rating, :desc
38
+ end
39
+ connection.should have_last_search_with(:sort => 'average_rating_ft desc')
40
+ end
41
+
42
+ it 'orders by multiple fields' do
43
+ search do
44
+ order_by :average_rating, :desc
45
+ order_by :sort_title, :asc
46
+ end
47
+ connection.should have_last_search_with(:sort => 'average_rating_ft desc, sort_title_s asc')
48
+ end
49
+
50
+ it 'orders by random' do
51
+ search do
52
+ order_by :random
53
+ end
54
+ connection.searches.last[:sort].should =~ /^random_\d+ asc$/
55
+ end
56
+
57
+ it 'orders by score' do
58
+ search do
59
+ order_by :score, :desc
60
+ end
61
+ connection.should have_last_search_with(:sort => 'score desc')
62
+ end
63
+
64
+ it 'throws an ArgumentError if a bogus order direction is given' do
65
+ lambda do
66
+ search do
67
+ order_by :sort_title, :sideways
68
+ end
69
+ end.should raise_error(ArgumentError)
70
+ end
71
+
72
+ it 'throws an UnrecognizedFieldError if :distance is given for sort' do
73
+ lambda do
74
+ search do
75
+ order_by :distance, :asc
76
+ end
77
+ end.should raise_error(Sunspot::UnrecognizedFieldError)
78
+ end
79
+
80
+ it 'does not allow ordering by multiple-value fields' do
81
+ lambda do
82
+ search do
83
+ order_by :category_ids
84
+ end
85
+ end.should raise_error(ArgumentError)
86
+ end
87
+
88
+ it 'raises ArgumentError if bogus argument given to paginate' do
89
+ lambda do
90
+ search do
91
+ paginate :page => 4, :ugly => :puppy
92
+ end
93
+ end.should raise_error(ArgumentError)
94
+ end
95
+ end