load_balanced_tire 0.1

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 (121) hide show
  1. data/.gitignore +14 -0
  2. data/.travis.yml +29 -0
  3. data/Gemfile +4 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.markdown +760 -0
  6. data/Rakefile +78 -0
  7. data/examples/rails-application-template.rb +249 -0
  8. data/examples/tire-dsl.rb +876 -0
  9. data/lib/tire.rb +55 -0
  10. data/lib/tire/alias.rb +296 -0
  11. data/lib/tire/configuration.rb +30 -0
  12. data/lib/tire/dsl.rb +43 -0
  13. data/lib/tire/http/client.rb +62 -0
  14. data/lib/tire/http/clients/curb.rb +61 -0
  15. data/lib/tire/http/clients/faraday.rb +71 -0
  16. data/lib/tire/http/response.rb +27 -0
  17. data/lib/tire/index.rb +361 -0
  18. data/lib/tire/logger.rb +60 -0
  19. data/lib/tire/model/callbacks.rb +40 -0
  20. data/lib/tire/model/import.rb +26 -0
  21. data/lib/tire/model/indexing.rb +128 -0
  22. data/lib/tire/model/naming.rb +100 -0
  23. data/lib/tire/model/percolate.rb +99 -0
  24. data/lib/tire/model/persistence.rb +71 -0
  25. data/lib/tire/model/persistence/attributes.rb +143 -0
  26. data/lib/tire/model/persistence/finders.rb +66 -0
  27. data/lib/tire/model/persistence/storage.rb +69 -0
  28. data/lib/tire/model/search.rb +307 -0
  29. data/lib/tire/results/collection.rb +114 -0
  30. data/lib/tire/results/item.rb +86 -0
  31. data/lib/tire/results/pagination.rb +54 -0
  32. data/lib/tire/rubyext/hash.rb +8 -0
  33. data/lib/tire/rubyext/ruby_1_8.rb +7 -0
  34. data/lib/tire/rubyext/symbol.rb +11 -0
  35. data/lib/tire/search.rb +188 -0
  36. data/lib/tire/search/facet.rb +74 -0
  37. data/lib/tire/search/filter.rb +28 -0
  38. data/lib/tire/search/highlight.rb +37 -0
  39. data/lib/tire/search/query.rb +186 -0
  40. data/lib/tire/search/scan.rb +114 -0
  41. data/lib/tire/search/script_field.rb +23 -0
  42. data/lib/tire/search/sort.rb +25 -0
  43. data/lib/tire/tasks.rb +135 -0
  44. data/lib/tire/utils.rb +17 -0
  45. data/lib/tire/version.rb +22 -0
  46. data/test/fixtures/articles/1.json +1 -0
  47. data/test/fixtures/articles/2.json +1 -0
  48. data/test/fixtures/articles/3.json +1 -0
  49. data/test/fixtures/articles/4.json +1 -0
  50. data/test/fixtures/articles/5.json +1 -0
  51. data/test/integration/active_model_indexing_test.rb +51 -0
  52. data/test/integration/active_model_searchable_test.rb +114 -0
  53. data/test/integration/active_record_searchable_test.rb +446 -0
  54. data/test/integration/boolean_queries_test.rb +43 -0
  55. data/test/integration/count_test.rb +34 -0
  56. data/test/integration/custom_score_queries_test.rb +88 -0
  57. data/test/integration/dis_max_queries_test.rb +68 -0
  58. data/test/integration/dsl_search_test.rb +22 -0
  59. data/test/integration/explanation_test.rb +44 -0
  60. data/test/integration/facets_test.rb +259 -0
  61. data/test/integration/filtered_queries_test.rb +66 -0
  62. data/test/integration/filters_test.rb +63 -0
  63. data/test/integration/fuzzy_queries_test.rb +20 -0
  64. data/test/integration/highlight_test.rb +64 -0
  65. data/test/integration/index_aliases_test.rb +122 -0
  66. data/test/integration/index_mapping_test.rb +43 -0
  67. data/test/integration/index_store_test.rb +96 -0
  68. data/test/integration/index_update_document_test.rb +111 -0
  69. data/test/integration/mongoid_searchable_test.rb +309 -0
  70. data/test/integration/percolator_test.rb +111 -0
  71. data/test/integration/persistent_model_test.rb +130 -0
  72. data/test/integration/prefix_query_test.rb +43 -0
  73. data/test/integration/query_return_version_test.rb +70 -0
  74. data/test/integration/query_string_test.rb +52 -0
  75. data/test/integration/range_queries_test.rb +36 -0
  76. data/test/integration/reindex_test.rb +46 -0
  77. data/test/integration/results_test.rb +39 -0
  78. data/test/integration/scan_test.rb +56 -0
  79. data/test/integration/script_fields_test.rb +38 -0
  80. data/test/integration/sort_test.rb +36 -0
  81. data/test/integration/text_query_test.rb +39 -0
  82. data/test/models/active_model_article.rb +31 -0
  83. data/test/models/active_model_article_with_callbacks.rb +49 -0
  84. data/test/models/active_model_article_with_custom_document_type.rb +7 -0
  85. data/test/models/active_model_article_with_custom_index_name.rb +7 -0
  86. data/test/models/active_record_models.rb +122 -0
  87. data/test/models/article.rb +15 -0
  88. data/test/models/mongoid_models.rb +97 -0
  89. data/test/models/persistent_article.rb +11 -0
  90. data/test/models/persistent_article_in_namespace.rb +12 -0
  91. data/test/models/persistent_article_with_casting.rb +28 -0
  92. data/test/models/persistent_article_with_defaults.rb +11 -0
  93. data/test/models/persistent_articles_with_custom_index_name.rb +10 -0
  94. data/test/models/supermodel_article.rb +17 -0
  95. data/test/models/validated_model.rb +11 -0
  96. data/test/test_helper.rb +93 -0
  97. data/test/unit/active_model_lint_test.rb +17 -0
  98. data/test/unit/configuration_test.rb +74 -0
  99. data/test/unit/http_client_test.rb +76 -0
  100. data/test/unit/http_response_test.rb +49 -0
  101. data/test/unit/index_alias_test.rb +275 -0
  102. data/test/unit/index_test.rb +894 -0
  103. data/test/unit/logger_test.rb +125 -0
  104. data/test/unit/model_callbacks_test.rb +116 -0
  105. data/test/unit/model_import_test.rb +71 -0
  106. data/test/unit/model_persistence_test.rb +528 -0
  107. data/test/unit/model_search_test.rb +913 -0
  108. data/test/unit/results_collection_test.rb +281 -0
  109. data/test/unit/results_item_test.rb +162 -0
  110. data/test/unit/rubyext_test.rb +66 -0
  111. data/test/unit/search_facet_test.rb +153 -0
  112. data/test/unit/search_filter_test.rb +42 -0
  113. data/test/unit/search_highlight_test.rb +46 -0
  114. data/test/unit/search_query_test.rb +301 -0
  115. data/test/unit/search_scan_test.rb +113 -0
  116. data/test/unit/search_script_field_test.rb +26 -0
  117. data/test/unit/search_sort_test.rb +50 -0
  118. data/test/unit/search_test.rb +499 -0
  119. data/test/unit/tire_test.rb +126 -0
  120. data/tire.gemspec +90 -0
  121. metadata +549 -0
@@ -0,0 +1,153 @@
1
+ require 'test_helper'
2
+
3
+ module Tire::Search
4
+
5
+ class FacetTest < Test::Unit::TestCase
6
+
7
+ context "Facet" do
8
+
9
+ should "be serialized to JSON" do
10
+ assert_respond_to Facet.new('foo'), :to_json
11
+ end
12
+
13
+ context "generally" do
14
+
15
+ should "encode facets with defaults for current query" do
16
+ assert_equal( { :foo => { :terms => {:field=>'bar',:size=>10,:all_terms=>false} } }.to_json,
17
+ Facet.new('foo').terms(:bar).to_json )
18
+ end
19
+
20
+ should "encode facets as global" do
21
+ assert_equal( { :foo => { :terms => {:field=>'bar',:size=>10,:all_terms=>false}, :global => true } }.to_json,
22
+ Facet.new('foo', :global => true).terms(:bar).to_json )
23
+ end
24
+
25
+ should "pass options to facets" do
26
+ payload = Facet.new('foo', :facet_filter => { :term => { :account_id => 'foo' } }).terms(:bar).to_hash
27
+
28
+ assert_not_nil payload['foo'][:facet_filter]
29
+ assert_equal( { :term => { :account_id => 'foo' } },
30
+ payload['foo'][:facet_filter] )
31
+ end
32
+
33
+ should "encode facet options" do
34
+ assert_equal( { :foo => { :terms => {:field=>'bar',:size=>5,:all_terms=>false} } }.to_json,
35
+ Facet.new('foo').terms(:bar, :size => 5).to_json )
36
+ end
37
+
38
+ should "encode facets when passed as a block" do
39
+ f = Facet.new('foo') do
40
+ terms :bar
41
+ end
42
+ assert_equal( { :foo => { :terms => {:field=>'bar',:size=>10,:all_terms=>false} } }.to_json, f.to_json )
43
+ end
44
+
45
+ should "encode facets when passed as a block, using variables from outer scope" do
46
+ def foo; 'bar'; end
47
+
48
+ f = Facet.new('foo') do |facet|
49
+ facet.terms foo, :size => 20
50
+ end
51
+ assert_equal( { :foo => { :terms => {:field=>'bar',:size=>20,:all_terms=>false} } }.to_json, f.to_json )
52
+ end
53
+
54
+ end
55
+
56
+ context "terms facet" do
57
+
58
+ should "encode the default all_terms option" do
59
+ assert_equal false, Facet.new('foo') { terms :foo }.to_hash['foo'][:terms][:all_terms]
60
+ end
61
+
62
+ should "encode the all_terms option" do
63
+ assert_equal true, Facet.new('foo') { terms :foo, :all_terms => true }.to_hash['foo'][:terms][:all_terms]
64
+ end
65
+
66
+ should "encode custom options" do
67
+ assert_equal( { :foo => { :terms => {:field=>'bar',:size=>5,:all_terms=>false,:exclude=>['moo']} } }.to_json,
68
+ Facet.new('foo').terms(:bar, :size => 5, :exclude => ['moo']).to_json )
69
+ end
70
+
71
+ end
72
+
73
+ context "date histogram" do
74
+
75
+ should "encode the JSON with default values" do
76
+ f = Facet.new('date') { date :published_on }
77
+ assert_equal({ :date => { :date_histogram => { :field => 'published_on', :interval => 'day' } } }.to_json, f.to_json)
78
+ end
79
+
80
+ should "encode the JSON with custom interval" do
81
+ f = Facet.new('date') { date :published_on, :interval => 'month' }
82
+ assert_equal({ :date => { :date_histogram => { :field => 'published_on', :interval => 'month' } } }.to_json, f.to_json)
83
+ end
84
+
85
+ should "encode custom options" do
86
+ f = Facet.new('date') { date :published_on, :value_field => 'price' }
87
+ assert_equal( {:date=>{:date_histogram=>{:field=>'published_on',:interval=>'day',:value_field=>'price' } } }.to_json,
88
+ f.to_json )
89
+ end
90
+
91
+ end
92
+
93
+ context "range facet" do
94
+ should "encode facet options" do
95
+ f = Facet.new('range') { range :published_on, [{:to => '2010-12-31'}, {:from => '2011-01-01', :to => '2011-05-27'}, {:from => '2011-05-28'}]}
96
+ assert_equal({ :range => { :range => { :field => 'published_on', :ranges => [{:to => '2010-12-31'}, {:from => '2011-01-01', :to => '2011-05-27'}, {:from => '2011-05-28'}] } } }.to_json, f.to_json)
97
+ end
98
+ end
99
+
100
+ context "histogram facet" do
101
+ should "encode facet options with default key" do
102
+ f = Facet.new('histogram') { histogram :age, {:interval => 5} }
103
+ assert_equal({ :histogram => { :histogram => { :field => 'age', :interval => 5 } } }.to_json, f.to_json)
104
+ end
105
+
106
+ should "encode the JSON if define an histogram" do
107
+ f = Facet.new('histogram') { histogram :age, {:histogram => {:key_field => "age", :value_field => "age", :interval => 100}} }
108
+ assert_equal({ :histogram => { :histogram => {:key_field => "age", :value_field => "age", :interval => 100} } }.to_json, f.to_json)
109
+ end
110
+ end
111
+
112
+ context "statistical facet" do
113
+ should "encode facet options" do
114
+ f = Facet.new('statistical') { statistical :words }
115
+ assert_equal({:statistical => {:statistical => {:field => 'words'}}}.to_json, f.to_json)
116
+ end
117
+
118
+ should "encode the JSON if a 'statistical' custom option is defined" do
119
+ f = Facet.new('statistical') { statistical :words, :statistical => {:params => {:factor => 5}} }
120
+ assert_equal({:statistical => {:statistical => {:params => {:factor => 5 }}}}.to_json, f.to_json)
121
+ end
122
+ end
123
+
124
+ context "terms_stats facet" do
125
+ should "should encode facet options" do
126
+ f = Facet.new('terms_stats') { terms_stats :tags, :words }
127
+ assert_equal({:terms_stats => {:terms_stats => {:key_field => 'tags', :value_field => 'words'}}}.to_json, f.to_json)
128
+ end
129
+ end
130
+
131
+ context "query facet" do
132
+ should "encode facet options" do
133
+ f = Facet.new('q_facet') do
134
+ query { string '_exists_:foo' }
135
+ end
136
+ assert_equal({ :q_facet => { :query => { :query_string => { :query => '_exists_:foo' } } } }.to_json, f.to_json)
137
+ end
138
+ end
139
+
140
+ context "filter facet" do
141
+ should "encode facet options" do
142
+ f = Facet.new('filter_facet') do
143
+ filter :tags, 'ruby'
144
+ end
145
+ assert_equal({ :filter_facet => { :filter => { :term => { :tags => 'ruby' } } } }.to_json, f.to_json)
146
+ end
147
+ end
148
+
149
+ end
150
+
151
+ end
152
+
153
+ end
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+
3
+ module Tire::Search
4
+
5
+ class FilterTest < Test::Unit::TestCase
6
+
7
+ context "Filter" do
8
+
9
+ should "be serialized to JSON" do
10
+ assert_respond_to Filter.new(:terms, {}), :to_json
11
+ end
12
+
13
+ should "encode simple filter declarations as JSON" do
14
+ assert_equal( { :terms => {} }.to_json,
15
+ Filter.new('terms').to_json )
16
+
17
+ assert_equal( { :terms => { :tags => ['foo'] } }.to_json,
18
+ Filter.new('terms', :tags => ['foo']).to_json )
19
+
20
+ assert_equal( { :range => { :age => { :from => 10, :to => 20 } } }.to_json,
21
+ Filter.new('range', { :age => { :from => 10, :to => 20 } }).to_json )
22
+
23
+ assert_equal( { :geo_distance => { :distance => '12km', :location => [40, -70] } }.to_json,
24
+ Filter.new('geo_distance', { :distance => '12km', :location => [40, -70] }).to_json )
25
+ end
26
+
27
+ should "encode 'or' filter with multiple other filters" do
28
+ # See http://www.elasticsearch.org/guide/reference/query-dsl/or-filter.html
29
+ assert_equal( { :or => [ {:terms => {:tags => ['foo']}}, {:terms => {:tags => ['bar']}} ] }.to_json,
30
+ Filter.new('or', {:terms => {:tags => ['foo']}}, {:terms => {:tags => ['bar']}}).to_json )
31
+ end
32
+
33
+ should "encode 'bool' filter with multiple filters" do
34
+ # http://www.elasticsearch.org/guide/reference/query-dsl/bool-filter.html
35
+ assert_equal( { :bool => [ {:must => {:terms => {:tags => ['foo']}}}, {:should => {:terms => {:tags => ['bar']}}} ] }.to_json,
36
+ Filter.new('bool', {:must => {:terms => {:tags => ['foo']}}}, { :should => {:terms => {:tags => ['bar']}}}).to_json )
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,46 @@
1
+ require 'test_helper'
2
+
3
+ module Tire::Search
4
+
5
+ class HighlightTest < Test::Unit::TestCase
6
+
7
+ context "Highlight" do
8
+
9
+ should "be serialized to JSON" do
10
+ assert_respond_to Highlight.new(:body), :to_json
11
+ end
12
+
13
+ should "specify highlight for single field" do
14
+ assert_equal( {:fields => { :body => {} }}.to_json,
15
+ Highlight.new(:body).to_json )
16
+ end
17
+
18
+ should "specify highlight for more fields" do
19
+ assert_equal( {:fields => { :title => {}, :body => {} }}.to_json,
20
+ Highlight.new(:title, :body).to_json )
21
+ end
22
+
23
+ should "specify highlight for more fields with options" do
24
+ assert_equal( {:fields => { :title => {}, :body => { :a => 1, :b => 2 } }}.to_json,
25
+ Highlight.new(:title, :body => { :a => 1, :b => 2 }).to_json )
26
+ end
27
+
28
+ should "specify highlight for more fields with highlight options" do
29
+ # p Highlight.new(:title, :body => {}, :options => { :tag => '<strong>' }).to_hash
30
+ assert_equal( {:fields => { :title => {}, :body => {} }, :pre_tags => ['<strong>'], :post_tags => ['</strong>'] }.to_json,
31
+ Highlight.new(:title, :body => {}, :options => { :tag => '<strong>' }).to_json )
32
+ end
33
+
34
+ context "with custom tags" do
35
+
36
+ should "properly parse tags with class" do
37
+ assert_equal( {:fields => { :title => {} }, :pre_tags => ['<strong class="highlight">'], :post_tags => ['</strong>'] }.to_json,
38
+ Highlight.new(:title, :options => { :tag => '<strong class="highlight">' }).to_json )
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,301 @@
1
+ require 'test_helper'
2
+
3
+ module Tire::Search
4
+
5
+ class QueryTest < Test::Unit::TestCase
6
+
7
+ context "Query" do
8
+ should "be serialized to JSON" do
9
+ assert_respond_to Query.new, :to_json
10
+ end
11
+
12
+ should "return itself as a Hash" do
13
+ assert_respond_to Query.new, :to_hash
14
+ assert_equal( { :term => { :foo => { :term => 'bar' } } }, Query.new.term(:foo, 'bar').to_hash )
15
+ end
16
+
17
+ should "allow a block to be given" do
18
+ assert_equal( { :term => { :foo => { :term => 'bar' } } }.to_json, Query.new do
19
+ term(:foo, 'bar')
20
+ end.to_json)
21
+ end
22
+ end
23
+
24
+ context "Term query" do
25
+ should "allow search for single term" do
26
+ assert_equal( { :term => { :foo => { :term => 'bar' } } }, Query.new.term(:foo, 'bar') )
27
+ end
28
+
29
+ should "allow search for single term passing an options hash" do
30
+ assert_equal( { :term => { :foo => { :term => 'bar', :boost => 2.0 } } }, Query.new.term(:foo, 'bar', :boost => 2.0) )
31
+ end
32
+ end
33
+
34
+ context "Terms query" do
35
+ should "allow search for multiple terms" do
36
+ assert_equal( { :terms => { :foo => ['bar', 'baz'] } }, Query.new.terms(:foo, ['bar', 'baz']) )
37
+ end
38
+
39
+ should "allow set minimum match when searching for multiple terms" do
40
+ assert_equal( { :terms => { :foo => ['bar', 'baz'], :minimum_match => 2 } },
41
+ Query.new.terms(:foo, ['bar', 'baz'], :minimum_match => 2) )
42
+ end
43
+ end
44
+
45
+ context "Range query" do
46
+ should "allow search for a range" do
47
+ assert_equal( { :range => { :age => { :gte => 21 } } }, Query.new.range(:age, { :gte => 21 }) )
48
+ end
49
+ end
50
+
51
+ context "Text query" do
52
+ should "allow search with a text search" do
53
+ assert_equal( { :text => {'field' => {:query => 'foo'}}}, Query.new.text('field', 'foo'))
54
+ end
55
+
56
+ should "allow search with a different operator for text search" do
57
+ assert_equal( { :text => {'field' => {:query => 'foo', :operator => 'and'}}},
58
+ Query.new.text('field', 'foo', :operator => 'and'))
59
+ end
60
+ end
61
+
62
+ context "Query String query" do
63
+ should "allow search with a query string" do
64
+ assert_equal( { :query_string => { :query => 'title:foo' } },
65
+ Query.new.string('title:foo') )
66
+ end
67
+
68
+ should "allow set default field when searching with a query string" do
69
+ assert_equal( { :query_string => { :query => 'foo', :default_field => 'title' } },
70
+ Query.new.string('foo', :default_field => 'title') )
71
+ end
72
+
73
+ should "allow set default operator when searching with a query string" do
74
+ assert_equal( { :query_string => { :query => 'foo', :default_operator => 'AND' } },
75
+ Query.new.string('foo', :default_operator => 'AND') )
76
+ end
77
+
78
+ should "allow to set options when searching with a query string" do
79
+ assert_equal( { :query_string => { :query => 'foo', :fields => ['title.*'], :use_dis_max => true } },
80
+ Query.new.string('foo', :fields => ['title.*'], :use_dis_max => true) )
81
+ end
82
+ end
83
+
84
+ context "Custom Score query" do
85
+ should "allow to set script for custom score queries" do
86
+ query = Query.new.custom_score(:script => "_score * doc['price'].value") do
87
+ string 'foo'
88
+ end
89
+
90
+ assert_equal "_score * doc['price'].value", query[:custom_score][:script]
91
+ end
92
+
93
+ should "allow to pass parameters for custom score queries" do
94
+ query = Query.new.custom_score(:script => "_score * doc['price'].value / max(a, b)",
95
+ :params => { :a => 1, :b => 2 }) do
96
+ string 'foo'
97
+ end
98
+
99
+ assert_equal 1, query[:custom_score][:params][:a]
100
+ assert_equal 2, query[:custom_score][:params][:b]
101
+ end
102
+ end
103
+
104
+ context "All query" do
105
+ should "search for all documents" do
106
+ assert_equal( { :match_all => { } }, Query.new.all )
107
+ end
108
+ end
109
+
110
+ context "IDs query" do
111
+ should "search for documents by IDs" do
112
+ assert_equal( { :ids => { :values => [1, 2], :type => 'foo' } },
113
+ Query.new.ids([1, 2], 'foo') )
114
+ end
115
+ end
116
+
117
+ context "FuzzyQuery" do
118
+
119
+ should "allow a fuzzy search" do
120
+ assert_equal( { :fuzzy => { :foo => { :term => 'bar' } } }, Query.new.fuzzy(:foo, 'bar') )
121
+ end
122
+
123
+ should "allow a fuzzy search with an options hash" do
124
+ assert_equal( { :term => { :foo => { :term => 'bar', :boost => 1.0, :min_similarity => 0.5 } } }, Query.new.term(:foo, 'bar', :boost => 1.0, :min_similarity => 0.5 ) )
125
+ end
126
+
127
+ end
128
+
129
+ context "BooleanQuery" do
130
+
131
+ should "not raise an error when no block is given" do
132
+ assert_nothing_raised { Query.new.boolean }
133
+ end
134
+
135
+ should "encode options" do
136
+ query = Query.new.boolean(:minimum_number_should_match => 1) do
137
+ must { string 'foo' }
138
+ end
139
+
140
+ assert_equal 1, query[:bool][:minimum_number_should_match]
141
+ end
142
+
143
+ should "wrap single query" do
144
+ assert_equal( { :bool => {:must => [{ :query_string => { :query => 'foo' } }] }},
145
+ Query.new.boolean { must { string 'foo' } } )
146
+ end
147
+
148
+ should "wrap multiple queries for the same condition" do
149
+ query = Query.new.boolean do
150
+ must { string 'foo' }
151
+ must { string 'bar' }
152
+ end
153
+
154
+ assert_equal( 2, query[:bool][:must].size, query[:bool][:must].inspect )
155
+ assert_equal( { :query_string => {:query => 'foo'} }, query[:bool][:must].first )
156
+ assert_equal( { :query_string => {:query => 'bar'} }, query[:bool][:must].last )
157
+ end
158
+
159
+ should "wrap queries for multiple conditions" do
160
+ query = Query.new.boolean do
161
+ should { string 'foo' }
162
+ must { string 'bar' }
163
+ must { string 'baz' }
164
+ must_not { string 'fuu' }
165
+ end
166
+
167
+ assert_equal 2, query[:bool][:must].size
168
+ assert_equal 1, query[:bool][:should].size
169
+ assert_equal 1, query[:bool][:must_not].size
170
+
171
+ assert_equal( { :query_string => {:query => 'foo'} }, query[:bool][:should].first )
172
+ assert_equal( { :query_string => {:query => 'bar'} }, query[:bool][:must].first )
173
+ assert_equal( { :query_string => {:query => 'baz'} }, query[:bool][:must].last )
174
+ assert_equal( { :query_string => {:query => 'fuu'} }, query[:bool][:must_not].first )
175
+ end
176
+
177
+ should "allow passing variables from outer scope" do
178
+ @q1 = 'foo'
179
+ @q2 = 'bar'
180
+ query = Query.new.boolean do |boolean|
181
+ boolean.must { |query| query.string @q1 }
182
+ boolean.must { |query| query.string @q2 }
183
+ end
184
+
185
+ assert_equal( 2, query[:bool][:must].size, query[:bool][:must].inspect )
186
+ assert_equal( { :query_string => {:query => 'foo'} }, query[:bool][:must].first )
187
+ assert_equal( { :query_string => {:query => 'bar'} }, query[:bool][:must].last )
188
+ end
189
+
190
+ end
191
+
192
+ context "FilteredQuery" do
193
+
194
+ should "not raise an error when no block is given" do
195
+ assert_nothing_raised { Query.new.filtered }
196
+ end
197
+
198
+ should "properly encode filter" do
199
+ query = Query.new.filtered do
200
+ query { term :foo, 'bar' }
201
+ filter :terms, :tags => ['ruby']
202
+ end
203
+
204
+ query[:filtered].tap do |f|
205
+ assert_equal( { :term => { :foo => { :term => 'bar' } } }, f[:query].to_hash )
206
+ assert_equal( { :tags => ['ruby'] }, f[:filter][:and].first[:terms] )
207
+ end
208
+ end
209
+
210
+ should "properly encode multiple filters" do
211
+ query = Query.new.filtered do
212
+ query { term :foo, 'bar' }
213
+ filter :terms, :tags => ['ruby']
214
+ filter :terms, :tags => ['python']
215
+ end
216
+
217
+ query[:filtered][:filter].tap do |filter|
218
+ assert_equal 1, filter.size
219
+ assert_equal( { :tags => ['ruby'] }, filter[:and].first[:terms] )
220
+ assert_equal( { :tags => ['python'] }, filter[:and].last[:terms] )
221
+ end
222
+ end
223
+
224
+ should "allow passing variables from outer scope" do
225
+ @my_query = 'bar'
226
+ @my_filter = { :tags => ['ruby'] }
227
+
228
+ query = Query.new.filtered do |f|
229
+ f.query { |q| q.term :foo, @my_query }
230
+ f.filter :terms, @my_filter
231
+ end
232
+
233
+ query[:filtered].tap do |f|
234
+ assert_equal( { :term => { :foo => { :term => 'bar' } } }, f[:query].to_hash )
235
+ assert_equal( { :tags => ['ruby'] }, f[:filter][:and].first[:terms] )
236
+ end
237
+ end
238
+
239
+ context "Prefix query" do
240
+ should "allow search for a prefix" do
241
+ assert_equal( { :prefix => { :user => "foo" } }, Query.new.prefix(:user, "foo") )
242
+ end
243
+
244
+ should "allow setting boost for prefix" do
245
+ assert_equal( { :prefix => {:user => {:prefix => "foo", :boost => 2.0 } } },
246
+ Query.new.prefix(:user, "foo", :boost => 2.0) )
247
+ end
248
+ end
249
+
250
+ end
251
+
252
+ context "DisMaxQuery" do
253
+
254
+ should "not raise an error when no block is given" do
255
+ assert_nothing_raised { Query.new.dis_max }
256
+ end
257
+
258
+ should "encode options" do
259
+ query = Query.new.dis_max(:tie_breaker => 0.7) do
260
+ query { string 'foo' }
261
+ end
262
+
263
+ assert_equal 0.7, query[:dis_max][:tie_breaker]
264
+ end
265
+
266
+ should "wrap single query" do
267
+ assert_equal( { :dis_max => {:queries => [{ :query_string => { :query => 'foo' } }] }},
268
+ Query.new.dis_max { query { string 'foo' } } )
269
+ end
270
+
271
+ should "wrap multiple queries" do
272
+ query = Query.new.dis_max do
273
+ query { string 'foo' }
274
+ query { string 'bar' }
275
+ query { string 'baz' }
276
+ end
277
+
278
+ assert_equal 3, query[:dis_max][:queries].size
279
+
280
+ assert_equal( { :query_string => {:query => 'foo'} }, query[:dis_max][:queries][0] )
281
+ assert_equal( { :query_string => {:query => 'bar'} }, query[:dis_max][:queries][1] )
282
+ assert_equal( { :query_string => {:query => 'baz'} }, query[:dis_max][:queries][2] )
283
+ end
284
+
285
+ should "allow passing variables from outer scope" do
286
+ @q1 = 'foo'
287
+ @q2 = 'bar'
288
+ query = Query.new.dis_max do |dis_max|
289
+ dis_max.query { |query| query.string @q1 }
290
+ dis_max.query { |query| query.string @q2 }
291
+ end
292
+
293
+ assert_equal( 2, query[:dis_max][:queries].size, query[:dis_max][:queries].inspect )
294
+ assert_equal( { :query_string => {:query => 'foo'} }, query[:dis_max][:queries].first )
295
+ assert_equal( { :query_string => {:query => 'bar'} }, query[:dis_max][:queries].last )
296
+ end
297
+
298
+ end
299
+
300
+ end
301
+ end