tire 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/.yardopts +1 -0
- data/README.markdown +2 -2
- data/examples/rails-application-template.rb +20 -6
- data/lib/tire.rb +2 -0
- data/lib/tire/alias.rb +1 -1
- data/lib/tire/configuration.rb +8 -0
- data/lib/tire/dsl.rb +69 -2
- data/lib/tire/index.rb +33 -20
- data/lib/tire/model/indexing.rb +7 -1
- data/lib/tire/model/persistence.rb +7 -4
- data/lib/tire/model/persistence/attributes.rb +1 -1
- data/lib/tire/model/persistence/finders.rb +4 -16
- data/lib/tire/model/search.rb +21 -8
- data/lib/tire/multi_search.rb +263 -0
- data/lib/tire/results/collection.rb +78 -49
- data/lib/tire/results/item.rb +6 -3
- data/lib/tire/results/pagination.rb +15 -1
- data/lib/tire/rubyext/ruby_1_8.rb +1 -7
- data/lib/tire/rubyext/uri_escape.rb +74 -0
- data/lib/tire/search.rb +33 -11
- data/lib/tire/search/facet.rb +8 -3
- data/lib/tire/search/filter.rb +1 -1
- data/lib/tire/search/highlight.rb +1 -1
- data/lib/tire/search/queries/match.rb +40 -0
- data/lib/tire/search/query.rb +42 -6
- data/lib/tire/search/scan.rb +1 -1
- data/lib/tire/search/script_field.rb +1 -1
- data/lib/tire/search/sort.rb +1 -1
- data/lib/tire/tasks.rb +17 -14
- data/lib/tire/version.rb +26 -8
- data/test/integration/active_record_searchable_test.rb +248 -129
- data/test/integration/boosting_queries_test.rb +32 -0
- data/test/integration/custom_score_queries_test.rb +1 -0
- data/test/integration/dsl_search_test.rb +9 -1
- data/test/integration/facets_test.rb +19 -6
- data/test/integration/match_query_test.rb +79 -0
- data/test/integration/multi_search_test.rb +114 -0
- data/test/integration/persistent_model_test.rb +58 -0
- data/test/models/article.rb +1 -1
- data/test/models/persistent_article_in_index.rb +16 -0
- data/test/models/persistent_article_with_defaults.rb +4 -3
- data/test/test_helper.rb +3 -1
- data/test/unit/configuration_test.rb +10 -0
- data/test/unit/index_test.rb +69 -27
- data/test/unit/model_initialization_test.rb +31 -0
- data/test/unit/model_persistence_test.rb +21 -7
- data/test/unit/model_search_test.rb +56 -5
- data/test/unit/multi_search_test.rb +304 -0
- data/test/unit/results_collection_test.rb +42 -2
- data/test/unit/results_item_test.rb +4 -0
- data/test/unit/search_facet_test.rb +35 -11
- data/test/unit/search_query_test.rb +96 -0
- data/test/unit/search_test.rb +60 -3
- data/test/unit/tire_test.rb +14 -0
- data/tire.gemspec +0 -1
- metadata +75 -44
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Tire
|
4
|
+
|
5
|
+
class BoostingQueriesIntegrationTest < Test::Unit::TestCase
|
6
|
+
include Test::Integration
|
7
|
+
|
8
|
+
context "Boosting queries" do
|
9
|
+
|
10
|
+
should "allow to set multiple queries per condition" do
|
11
|
+
s = Tire.search('articles-test') do
|
12
|
+
query do
|
13
|
+
boosting(:negative_boost => 0.2) do
|
14
|
+
positive do
|
15
|
+
string "Two One"
|
16
|
+
end
|
17
|
+
negative do
|
18
|
+
term :tags, 'python'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
assert_equal 'One', s.results[0].title
|
25
|
+
assert_equal 'Two', s.results[1].title
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -10,11 +10,19 @@ module Tire
|
|
10
10
|
should "allow passing search payload as a Hash" do
|
11
11
|
s = Tire.search 'articles-test', :query => { :query_string => { :query => 'ruby' } },
|
12
12
|
:facets => { 'tags' => { :filter => { :term => {:tags => 'ruby' } } } }
|
13
|
-
|
13
|
+
|
14
14
|
assert_equal 2, s.results.count
|
15
15
|
assert_equal 2, s.results.facets['tags']['count']
|
16
16
|
end
|
17
17
|
|
18
|
+
should "allow building search query iteratively" do
|
19
|
+
s = Tire.search 'articles-test'
|
20
|
+
s.query { string 'T*' }
|
21
|
+
s.filter :terms, :tags => ['java']
|
22
|
+
|
23
|
+
assert_equal 1, s.results.count
|
24
|
+
end
|
25
|
+
|
18
26
|
end
|
19
27
|
|
20
28
|
end
|
@@ -59,6 +59,21 @@ module Tire
|
|
59
59
|
assert_equal 1, s.results.facets['tags']['terms'].first['count'].to_i
|
60
60
|
end
|
61
61
|
|
62
|
+
should "allow to define the facet filter with DSL" do
|
63
|
+
s = Tire.search('articles-test', :search_type => 'count') do
|
64
|
+
facet 'tags' do
|
65
|
+
terms :tags
|
66
|
+
facet_filter :range, { :published_on => { :from => '2011-01-01', :to => '2011-01-01' } }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_equal 1, s.results.facets.size
|
71
|
+
assert_equal 'ruby', s.results.facets['tags']['terms'].first['term']
|
72
|
+
assert_equal 1, s.results.facets['tags']['terms'].first['count'].to_i
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
62
77
|
context "terms" do
|
63
78
|
setup do
|
64
79
|
@s = Tire.search('articles-test') do
|
@@ -238,19 +253,17 @@ module Tire
|
|
238
253
|
end
|
239
254
|
|
240
255
|
context "filter" do
|
241
|
-
|
242
|
-
|
243
|
-
|
256
|
+
|
257
|
+
should "return a filter facet" do
|
258
|
+
s = Tire.search('articles-test', :search_type => 'count') do
|
244
259
|
facet 'filtered' do
|
245
|
-
filter :
|
260
|
+
filter :range, :words => { :from => 100, :to => 200 }
|
246
261
|
end
|
247
262
|
end
|
248
263
|
|
249
|
-
assert_equal 5, s.results.size, s.results.inspect
|
250
264
|
facets = s.results.facets["filtered"]
|
251
265
|
assert_equal 2, facets["count"], facets.inspect
|
252
266
|
end
|
253
|
-
end
|
254
267
|
|
255
268
|
end
|
256
269
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Tire
|
4
|
+
|
5
|
+
class MatchQueryIntegrationTest < Test::Unit::TestCase
|
6
|
+
include Test::Integration
|
7
|
+
|
8
|
+
context "Match query" do
|
9
|
+
setup do
|
10
|
+
Tire.index 'match-query-test' do
|
11
|
+
delete
|
12
|
+
create settings: { index: { number_of_shards: 1, number_of_replicas: 0 } },
|
13
|
+
mappings: {
|
14
|
+
document: { properties: {
|
15
|
+
last_name: { type: 'string', analyzer: 'english' },
|
16
|
+
age: { type: 'integer' }
|
17
|
+
} }
|
18
|
+
}
|
19
|
+
|
20
|
+
store first_name: 'John', last_name: 'Smith', age: 30, gender: 'male'
|
21
|
+
store first_name: 'John', last_name: 'Smithson', age: 25, gender: 'male'
|
22
|
+
store first_name: 'Adam', last_name: 'Smith', age: 75, gender: 'male'
|
23
|
+
store first_name: 'Mary', last_name: 'John', age: 30, gender: 'female'
|
24
|
+
refresh
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
teardown do
|
29
|
+
Tire.index('match-query-test').delete
|
30
|
+
end
|
31
|
+
|
32
|
+
should "find documents by single field" do
|
33
|
+
s = Tire.search 'match-query-test' do
|
34
|
+
query do
|
35
|
+
match :last_name, 'Smith'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
assert_equal 2, s.results.count
|
40
|
+
end
|
41
|
+
|
42
|
+
should "find document by multiple fields with multi_match" do
|
43
|
+
s = Tire.search 'match-query-test' do
|
44
|
+
query do
|
45
|
+
match [:first_name, :last_name], 'John'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
assert_equal 3, s.results.count
|
50
|
+
end
|
51
|
+
|
52
|
+
should "find documents by prefix" do
|
53
|
+
s = Tire.search 'match-query-test' do
|
54
|
+
query do
|
55
|
+
match :last_name, 'Smi', type: 'phrase_prefix'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
assert_equal 3, s.results.count
|
60
|
+
end
|
61
|
+
|
62
|
+
should "automatically create a boolean query when called repeatedly" do
|
63
|
+
s = Tire.search 'match-query-test' do
|
64
|
+
query do
|
65
|
+
match [:first_name, :last_name], 'John'
|
66
|
+
match :age, 30
|
67
|
+
match :gender, 'male'
|
68
|
+
end
|
69
|
+
# puts to_curl
|
70
|
+
end
|
71
|
+
|
72
|
+
assert_equal 1, s.results.count
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Tire
|
4
|
+
|
5
|
+
class MultiSearchIntegrationTest < Test::Unit::TestCase
|
6
|
+
include Test::Integration
|
7
|
+
|
8
|
+
context "Multi search" do
|
9
|
+
# Tire.configure { logger STDERR }
|
10
|
+
setup do
|
11
|
+
Tire.index 'multi-search-test-1' do
|
12
|
+
delete
|
13
|
+
create
|
14
|
+
store first_name: 'John', last_name: 'Smith', age: 30, gender: 'male'
|
15
|
+
store first_name: 'John', last_name: 'Smithson', age: 25, gender: 'male'
|
16
|
+
store first_name: 'Mary', last_name: 'Smith', age: 20, gender: 'female'
|
17
|
+
refresh
|
18
|
+
end
|
19
|
+
Tire.index 'multi-search-test-2' do
|
20
|
+
delete
|
21
|
+
create
|
22
|
+
store first_name: 'John', last_name: 'Milton', age: 35, gender: 'male'
|
23
|
+
store first_name: 'Mary', last_name: 'Milson', age: 44, gender: 'female'
|
24
|
+
store first_name: 'Mary', last_name: 'Reilly', age: 55, gender: 'female'
|
25
|
+
refresh
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
teardown do
|
30
|
+
Tire.index('multi-search-test-1').delete
|
31
|
+
Tire.index('multi-search-test-2').delete
|
32
|
+
end
|
33
|
+
|
34
|
+
should "return multiple results" do
|
35
|
+
s = Tire.multi_search 'multi-search-test-1' do
|
36
|
+
search :johns do
|
37
|
+
query { match :_all, 'john' }
|
38
|
+
end
|
39
|
+
search :males do
|
40
|
+
query { match :gender, 'male' }
|
41
|
+
end
|
42
|
+
search :facets, search_type: 'count' do
|
43
|
+
facet('age') { statistical :age }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_equal 3, s.results.size
|
48
|
+
|
49
|
+
assert_equal 2, s.results[:johns].size
|
50
|
+
assert_equal 2, s.results[:males].size
|
51
|
+
|
52
|
+
assert s.results[:facets].results.empty?, "Results not empty? #{s.results[:facets].results}"
|
53
|
+
assert_equal 75.0, s.results[:facets].facets['age']['total']
|
54
|
+
end
|
55
|
+
|
56
|
+
should "mix named and numbered searches" do
|
57
|
+
s = Tire.multi_search 'multi-search-test-1' do
|
58
|
+
search(:johns) { query { match :_all, 'john' } }
|
59
|
+
search { query { match :_all, 'mary' } }
|
60
|
+
end
|
61
|
+
|
62
|
+
assert_equal 2, s.results.size
|
63
|
+
|
64
|
+
assert_equal 2, s.results[:johns].size
|
65
|
+
assert_equal 1, s.results[1].size
|
66
|
+
end
|
67
|
+
|
68
|
+
should "iterate over mixed searches" do
|
69
|
+
s = Tire.multi_search 'multi-search-test-1' do
|
70
|
+
search(:johns) { query { match :_all, 'john' } }
|
71
|
+
search { query { match :_all, 'mary' } }
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_equal [:johns, 1], s.searches.names
|
75
|
+
assert_equal [:johns, 1], s.results.to_hash.keys
|
76
|
+
|
77
|
+
s.results.each_with_index do |results, i|
|
78
|
+
assert_equal 2, results.size if i == 0
|
79
|
+
assert_equal 1, results.size if i == 1
|
80
|
+
end
|
81
|
+
|
82
|
+
s.results.each_pair do |name, results|
|
83
|
+
assert_equal 2, results.size if name == :johns
|
84
|
+
assert_equal 1, results.size if name == 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
should "return results from different indices" do
|
89
|
+
s = Tire.multi_search do
|
90
|
+
search( index: 'multi-search-test-1' ) { query { match :_all, 'john' } }
|
91
|
+
search( index: 'multi-search-test-2' ) { query { match :_all, 'john' } }
|
92
|
+
end
|
93
|
+
|
94
|
+
assert_equal 2, s.results[0].size
|
95
|
+
assert_equal 1, s.results[1].size
|
96
|
+
end
|
97
|
+
|
98
|
+
should "return error for failed searches" do
|
99
|
+
s = Tire.multi_search 'multi-search-test-1' do
|
100
|
+
search() { query { match :_all, 'john' } }
|
101
|
+
search() { query { string '[x' } }
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_equal 2, s.results[0].size
|
105
|
+
assert s.results[0].success?
|
106
|
+
|
107
|
+
assert_equal 0, s.results[1].size
|
108
|
+
assert s.results[1].failure?
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -124,6 +124,64 @@ module Tire
|
|
124
124
|
|
125
125
|
end
|
126
126
|
|
127
|
+
context "multi search" do
|
128
|
+
setup do
|
129
|
+
# Tire.configure { logger STDERR }
|
130
|
+
PersistentArticle.create :title => 'Test'
|
131
|
+
PersistentArticle.create :title => 'Pest'
|
132
|
+
PersistentArticle.index.refresh
|
133
|
+
end
|
134
|
+
|
135
|
+
should "return multiple result sets" do
|
136
|
+
results = PersistentArticle.multi_search do
|
137
|
+
search do
|
138
|
+
query { match :title, 'test' }
|
139
|
+
end
|
140
|
+
search search_type: 'count' do
|
141
|
+
query { match :title, 'pest' }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
assert_equal 2, results.size
|
146
|
+
|
147
|
+
assert_equal 1, results[0].size
|
148
|
+
assert_equal 1, results[0].total
|
149
|
+
|
150
|
+
assert_equal 0, results[1].size
|
151
|
+
assert_equal 1, results[1].total
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "with multiple types within single index" do
|
156
|
+
|
157
|
+
setup do
|
158
|
+
# Create documents of two types within single index
|
159
|
+
PersistentArticleInIndex.create :title => "TestInIndex", :tags => ['in_index']
|
160
|
+
PersistentArticle.create :title => "Test", :tags => []
|
161
|
+
PersistentArticle.index.refresh
|
162
|
+
end
|
163
|
+
|
164
|
+
should "returns all documents with proper type" do
|
165
|
+
results = PersistentArticle.all
|
166
|
+
|
167
|
+
assert_equal 1, results.size
|
168
|
+
assert results.all? { |r| r.tags == [] }, "Incorrect results? " + results.to_a.inspect
|
169
|
+
|
170
|
+
results = PersistentArticleInIndex.all
|
171
|
+
|
172
|
+
assert_equal 1, results.size
|
173
|
+
assert results.all? { |r| r.tags == ['in_index'] }, "Incorrect results? " + results.to_a.inspect
|
174
|
+
end
|
175
|
+
|
176
|
+
should "returns first document with proper type" do
|
177
|
+
assert_instance_of PersistentArticle, PersistentArticle.first
|
178
|
+
assert_instance_of PersistentArticleInIndex, PersistentArticleInIndex.first
|
179
|
+
|
180
|
+
assert_equal [], PersistentArticle.first.tags
|
181
|
+
assert_equal ['in_index'], PersistentArticleInIndex.first.tags
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
127
185
|
end
|
128
186
|
|
129
187
|
end
|
data/test/models/article.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Example class with ElasticSearch persistence in index `persistent_articles`
|
2
|
+
#
|
3
|
+
# The `index` is `persistent_articles`
|
4
|
+
#
|
5
|
+
|
6
|
+
class PersistentArticleInIndex
|
7
|
+
|
8
|
+
include Tire::Model::Persistence
|
9
|
+
|
10
|
+
property :title
|
11
|
+
property :published_on
|
12
|
+
property :tags
|
13
|
+
|
14
|
+
index_name "persistent_articles"
|
15
|
+
|
16
|
+
end
|
@@ -4,8 +4,9 @@ class PersistentArticleWithDefaults
|
|
4
4
|
|
5
5
|
property :title
|
6
6
|
property :published_on
|
7
|
-
property :tags,
|
8
|
-
property :hidden,
|
9
|
-
property :options,
|
7
|
+
property :tags, :default => []
|
8
|
+
property :hidden, :default => false
|
9
|
+
property :options, :default => {:switches => []}
|
10
|
+
property :created_at, :default => lambda { Time.now }
|
10
11
|
|
11
12
|
end
|
data/test/test_helper.rb
CHANGED
@@ -24,6 +24,7 @@ require File.dirname(__FILE__) + '/models/active_model_article_with_custom_index
|
|
24
24
|
require File.dirname(__FILE__) + '/models/active_record_models'
|
25
25
|
require File.dirname(__FILE__) + '/models/article'
|
26
26
|
require File.dirname(__FILE__) + '/models/persistent_article'
|
27
|
+
require File.dirname(__FILE__) + '/models/persistent_article_in_index'
|
27
28
|
require File.dirname(__FILE__) + '/models/persistent_article_in_namespace'
|
28
29
|
require File.dirname(__FILE__) + '/models/persistent_article_with_casting'
|
29
30
|
require File.dirname(__FILE__) + '/models/persistent_article_with_defaults'
|
@@ -86,7 +87,8 @@ module Test::Integration
|
|
86
87
|
mongoid_class_with_tire_methods
|
87
88
|
supermodel_articles
|
88
89
|
dynamic_index
|
89
|
-
model_with_nested_documents
|
90
|
+
model_with_nested_documents
|
91
|
+
model_with_incorrect_mappings ].each do |index|
|
90
92
|
::RestClient.delete "#{URL}/#{index}" rescue nil
|
91
93
|
end
|
92
94
|
end
|
@@ -52,6 +52,16 @@ module Tire
|
|
52
52
|
assert_instance_of Tire::Logger, Configuration.logger
|
53
53
|
end
|
54
54
|
|
55
|
+
should "set pretty option to true by default" do
|
56
|
+
assert_not_nil Configuration.pretty
|
57
|
+
assert Configuration.pretty, "Should be true, but is: #{Configuration.pretty.inspect}"
|
58
|
+
end
|
59
|
+
|
60
|
+
should "set the pretty option to false" do
|
61
|
+
Configuration.pretty(false)
|
62
|
+
assert ! Configuration.pretty, "Should be falsy, but is: #{Configuration.pretty.inspect}"
|
63
|
+
end
|
64
|
+
|
55
65
|
should "allow to reset the configuration for specific property" do
|
56
66
|
Configuration.url 'http://example.com'
|
57
67
|
assert_equal 'http://example.com', Configuration.url
|