| 1 |
require File.dirname(__FILE__) + '/../test_helper' |
|---|
| 2 |
require 'pp' |
|---|
| 3 |
require 'fileutils' |
|---|
| 4 |
|
|---|
| 5 |
class MultiIndexTest < Test::Unit::TestCase |
|---|
| 6 |
include Ferret::Index |
|---|
| 7 |
include Ferret::Search |
|---|
| 8 |
fixtures :contents, :comments |
|---|
| 9 |
|
|---|
| 10 |
def setup |
|---|
| 11 |
#make sure the fixtures are in the index |
|---|
| 12 |
FileUtils.rm_f 'index/test/' |
|---|
| 13 |
Comment.rebuild_index |
|---|
| 14 |
ContentBase.rebuild_index |
|---|
| 15 |
raise "missing fixtures" unless ContentBase.count > 2 |
|---|
| 16 |
|
|---|
| 17 |
@another_content = Content.new( :title => 'Another Content item', |
|---|
| 18 |
:description => 'this is not the title' ) |
|---|
| 19 |
@another_content.save |
|---|
| 20 |
@comment = @another_content.comments.create(:author => 'john doe', :content => 'This is a useless comment') |
|---|
| 21 |
@comment2 = @another_content.comments.create(:author => 'another', :content => 'content') |
|---|
| 22 |
@another_content.save # to update comment_count in ferret-index |
|---|
| 23 |
end |
|---|
| 24 |
|
|---|
| 25 |
def teardown |
|---|
| 26 |
ContentBase.find(:all).each { |c| c.destroy } |
|---|
| 27 |
Comment.find(:all).each { |c| c.destroy } |
|---|
| 28 |
end |
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
# weiter: single index / multisearch lazy loading |
|---|
| 32 |
# def test_lazy_loading |
|---|
| 33 |
# results = Content.find_with_ferret 'description', :lazy => true |
|---|
| 34 |
# assert_equal 1, results.size |
|---|
| 35 |
# result = results.first |
|---|
| 36 |
# class << result |
|---|
| 37 |
# attr_accessor :ar_record # so we have a chance to check if it's been loaded... |
|---|
| 38 |
# end |
|---|
| 39 |
# assert ActsAsFerret::FerretResult === result |
|---|
| 40 |
# assert_equal 'A useless description', result.description |
|---|
| 41 |
# assert_nil result.instance_variable_get(:@ar_record) |
|---|
| 42 |
# assert_equal 'My Title', result.title |
|---|
| 43 |
# assert_not_nil result.ar_record |
|---|
| 44 |
# end |
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
def test_total_hits |
|---|
| 48 |
q = '*:title OR *:comment' |
|---|
| 49 |
assert_equal 3, Comment.total_hits(q) |
|---|
| 50 |
assert_equal 2, Content.total_hits(q) |
|---|
| 51 |
assert_equal 5, ActsAsFerret::total_hits(q, [ Comment, Content ]) |
|---|
| 52 |
end |
|---|
| 53 |
|
|---|
| 54 |
def test_sorting |
|---|
| 55 |
sorting = [ Ferret::Search::SortField.new(:id) ] |
|---|
| 56 |
result = ActsAsFerret::find('*:title OR *:comment', [Content, Comment], :sort => sorting) |
|---|
| 57 |
assert_equal result.map(&:id).sort, result.map(&:id) |
|---|
| 58 |
|
|---|
| 59 |
sorting = [ Ferret::Search::SortField.new(:title) ] |
|---|
| 60 |
result = ActsAsFerret::find('*:title OR *:comment', [Content, Comment], :sort => sorting) |
|---|
| 61 |
sorting = [ Ferret::Search::SortField.new(:title, :reverse => true) ] |
|---|
| 62 |
result2 = ActsAsFerret::find('*:title OR *:comment', [Content, Comment], :sort => sorting) |
|---|
| 63 |
assert result.any? |
|---|
| 64 |
assert result.map(&:id) != result2.map(&:id) |
|---|
| 65 |
|
|---|
| 66 |
result = ActsAsFerret::find('*:title OR *:comment', [Content, Comment ]) |
|---|
| 67 |
assert result.any? |
|---|
| 68 |
assert_equal result.map(&:ferret_score).sort.reverse, result.map(&:ferret_score) |
|---|
| 69 |
|
|---|
| 70 |
sorting = [ Ferret::Search::SortField::SCORE ] |
|---|
| 71 |
result = ActsAsFerret::find('*:title OR *:comment', [Content, Comment ], :sort => sorting) |
|---|
| 72 |
assert result.any? |
|---|
| 73 |
assert_equal result.map(&:ferret_score).sort.reverse, result.map(&:ferret_score) |
|---|
| 74 |
|
|---|
| 75 |
sorting = [ Ferret::Search::SortField::SCORE_REV ] |
|---|
| 76 |
result2 = ActsAsFerret::find('*:title OR *:comment', [Content, Comment], :sort => sorting) |
|---|
| 77 |
assert_equal result2.map(&:ferret_score).sort, result2.map(&:ferret_score) |
|---|
| 78 |
assert_equal result.map(&:ferret_score), result2.map(&:ferret_score).reverse |
|---|
| 79 |
end |
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
# remote index rebuilds will create an index in a directory with a timestamped name. |
|---|
| 83 |
# the local MultiIndex instance doesn't know about this (because it's running in |
|---|
| 84 |
# another interpreter instance than the server) and therefore fails to use the |
|---|
| 85 |
# correct index directories. |
|---|
| 86 |
# TODO strange, still doesn't work but it should now... |
|---|
| 87 |
unless Content.aaf_configuration[:remote] |
|---|
| 88 |
def test_multi_index |
|---|
| 89 |
i = ActsAsFerret::get_index_for Content, Comment |
|---|
| 90 |
assert ActsAsFerret::MultiIndex === i |
|---|
| 91 |
hits = i.search(TermQuery.new(:title,"title")) |
|---|
| 92 |
assert_equal 1, hits.total_hits |
|---|
| 93 |
|
|---|
| 94 |
qp = Ferret::QueryParser.new(:default_field => "title", |
|---|
| 95 |
:analyzer => Ferret::Analysis::WhiteSpaceAnalyzer.new) |
|---|
| 96 |
hits = i.search(qp.parse("title")) |
|---|
| 97 |
assert_equal 1, hits.total_hits |
|---|
| 98 |
|
|---|
| 99 |
qp = Ferret::QueryParser.new(:fields => ['title', 'content', 'description'], |
|---|
| 100 |
:analyzer => Ferret::Analysis::WhiteSpaceAnalyzer.new) |
|---|
| 101 |
hits = i.search(qp.parse("title")) |
|---|
| 102 |
assert_equal 2, hits.total_hits |
|---|
| 103 |
hits = i.search(qp.parse("title:title OR description:title")) |
|---|
| 104 |
assert_equal 2, hits.total_hits |
|---|
| 105 |
|
|---|
| 106 |
hits = i.search("title:title OR description:title OR title:comment OR description:comment OR content:comment") |
|---|
| 107 |
assert_equal 5, hits.total_hits |
|---|
| 108 |
|
|---|
| 109 |
hits = i.search("title OR comment") |
|---|
| 110 |
assert_equal 5, hits.total_hits |
|---|
| 111 |
|
|---|
| 112 |
hits = i.search("title OR comment", :limit => 2) |
|---|
| 113 |
count = 0 |
|---|
| 114 |
hits.hits.each { |hit, score| count += 1 } |
|---|
| 115 |
assert_equal 2, count |
|---|
| 116 |
|
|---|
| 117 |
hits = i.search("title OR comment", :offset => 2) |
|---|
| 118 |
count = 0 |
|---|
| 119 |
hits.hits.each { |hit, score| count += 1 } |
|---|
| 120 |
assert_equal 3, count |
|---|
| 121 |
end |
|---|
| 122 |
end |
|---|
| 123 |
|
|---|
| 124 |
def test_search_rebuilds_index |
|---|
| 125 |
remove_index Content |
|---|
| 126 |
contents_from_ferret = ActsAsFerret::find('description:title', [Content, Comment]) |
|---|
| 127 |
assert_equal 1, contents_from_ferret.size |
|---|
| 128 |
end |
|---|
| 129 |
|
|---|
| 130 |
# remote index rebuilds will create an index in a directory with a timestamped name... |
|---|
| 131 |
unless Content.aaf_configuration[:remote] |
|---|
| 132 |
def test_rebuilds_index |
|---|
| 133 |
remove_index Content |
|---|
| 134 |
idx = ActsAsFerret.get_index_for( Content ) |
|---|
| 135 |
i = ActsAsFerret::MultiIndex.new([idx]) |
|---|
| 136 |
assert File.exists?("#{idx.index_definition[:index_dir]}/segments") |
|---|
| 137 |
hits = i.search("description:title") |
|---|
| 138 |
assert_equal 1, hits.total_hits, hits.inspect |
|---|
| 139 |
end |
|---|
| 140 |
end |
|---|
| 141 |
|
|---|
| 142 |
def test_find_options |
|---|
| 143 |
contents_from_ferret = ActsAsFerret::find('title', [Content, Comment ], { }, :order => 'id desc') |
|---|
| 144 |
assert_equal 2, contents_from_ferret.size |
|---|
| 145 |
assert contents_from_ferret.first.id > contents_from_ferret.last.id |
|---|
| 146 |
contents_from_ferret = ActsAsFerret::find('title', [Content, Comment ], { }, :order => 'id asc') |
|---|
| 147 |
assert contents_from_ferret.first.id < contents_from_ferret.last.id |
|---|
| 148 |
|
|---|
| 149 |
contents_from_ferret = ActsAsFerret::find('title', [Content, Comment], :limit => 1) |
|---|
| 150 |
assert_equal 1, contents_from_ferret.size |
|---|
| 151 |
contents_from_ferret = ActsAsFerret::find('title', [Content, Comment ], { }, :limit => 1) |
|---|
| 152 |
assert_equal 1, contents_from_ferret.size |
|---|
| 153 |
|
|---|
| 154 |
|
|---|
| 155 |
more_contents(true) |
|---|
| 156 |
r = ActsAsFerret::find('title OR comment', [Content, Comment], { :limit => :all } ) |
|---|
| 157 |
assert_equal 60, r.size |
|---|
| 158 |
assert_equal 60, r.total_hits |
|---|
| 159 |
|
|---|
| 160 |
id = Content.find_with_ferret('title').first.id |
|---|
| 161 |
r = ActsAsFerret::find('title OR comment', [Content, Comment], { :limit => :all }, |
|---|
| 162 |
{ :conditions => { :content => ["id != ?", id] }}) |
|---|
| 163 |
assert_equal 59, r.size |
|---|
| 164 |
assert_equal 59, r.total_hits |
|---|
| 165 |
|
|---|
| 166 |
r = ActsAsFerret::find('title OR comment', [Content, Comment], { :limit => 20 }, |
|---|
| 167 |
{ :conditions => { :content => ["id != ?", id] }}) |
|---|
| 168 |
assert_equal 20, r.size |
|---|
| 169 |
assert_equal 59, r.total_hits |
|---|
| 170 |
|
|---|
| 171 |
r = ActsAsFerret::find('title OR comment', [Content, Comment], { :limit => 20 }, |
|---|
| 172 |
{ :conditions => { :comment => 'content is null', |
|---|
| 173 |
:content => ["id != ?", id] }}) |
|---|
| 174 |
assert_equal 20, r.size |
|---|
| 175 |
assert_equal 29, r.total_hits |
|---|
| 176 |
|
|---|
| 177 |
r = ActsAsFerret::find('title OR comment', [Content, Comment ], { }, |
|---|
| 178 |
{ :conditions => { :content => ["id != ?", id] }, :limit => 20 }) |
|---|
| 179 |
assert_equal 20, r.size |
|---|
| 180 |
assert_equal 59, r.total_hits |
|---|
| 181 |
end |
|---|
| 182 |
|
|---|
| 183 |
def test_multi_search |
|---|
| 184 |
assert_equal 4, ContentBase.find(:all).size |
|---|
| 185 |
|
|---|
| 186 |
Content.aaf_index.ferret_index.flush |
|---|
| 187 |
contents_from_ferret = ActsAsFerret::find('description:title', [Content]) |
|---|
| 188 |
assert_equal 1, contents_from_ferret.size |
|---|
| 189 |
contents_from_ferret = ActsAsFerret::find('title:title OR description:title', [Content]) |
|---|
| 190 |
assert_equal 2, contents_from_ferret.size |
|---|
| 191 |
contents_from_ferret = ActsAsFerret::find('title:title', [Content]) |
|---|
| 192 |
assert_equal 1, contents_from_ferret.size |
|---|
| 193 |
contents_from_ferret = ActsAsFerret::find('*:title', [Content]) |
|---|
| 194 |
assert_equal 2, contents_from_ferret.size |
|---|
| 195 |
contents_from_ferret = ActsAsFerret::find('title', [Content]) |
|---|
| 196 |
assert_equal 2, contents_from_ferret.size |
|---|
| 197 |
|
|---|
| 198 |
assert_equal contents(:first).id, contents_from_ferret.first.id |
|---|
| 199 |
assert_equal @another_content.id, contents_from_ferret.last.id |
|---|
| 200 |
|
|---|
| 201 |
contents_from_ferret = ActsAsFerret::find('title', [Content]) |
|---|
| 202 |
assert_equal 2, contents_from_ferret.size |
|---|
| 203 |
contents_from_ferret = ActsAsFerret::find('title', [Content], :limit => 1) |
|---|
| 204 |
assert_equal 1, contents_from_ferret.size |
|---|
| 205 |
contents_from_ferret = ActsAsFerret::find('title', [Content], :offset => 1) |
|---|
| 206 |
assert_equal 1, contents_from_ferret.size |
|---|
| 207 |
|
|---|
| 208 |
contents_from_ferret = ActsAsFerret::find('title:title OR content:comment OR description:title', [Content, Comment]) |
|---|
| 209 |
assert_equal 5, contents_from_ferret.size |
|---|
| 210 |
contents_from_ferret = ActsAsFerret::find('title:title OR content:comment OR description:title', [Content, Comment], :limit => 2) |
|---|
| 211 |
assert_equal 2, contents_from_ferret.size |
|---|
| 212 |
|
|---|
| 213 |
contents_from_ferret = ActsAsFerret::find('*:title OR *:comment', [Content, Comment]) |
|---|
| 214 |
assert_equal 5, contents_from_ferret.size |
|---|
| 215 |
contents_from_ferret = ActsAsFerret::find('*:title OR *:comment', [Content, Comment]) |
|---|
| 216 |
assert_equal 5, contents_from_ferret.size |
|---|
| 217 |
contents_from_ferret = ActsAsFerret::find('title:(title OR comment) OR description:(title OR comment) OR content:(title OR comment)', [Content, Comment]) |
|---|
| 218 |
assert_equal 5, contents_from_ferret.size |
|---|
| 219 |
end |
|---|
| 220 |
|
|---|
| 221 |
def test_lazy_search |
|---|
| 222 |
contents_from_ferret = ActsAsFerret.find('title', [Content, Comment], :lazy => true) |
|---|
| 223 |
assert_equal 2, contents_from_ferret.size |
|---|
| 224 |
contents_from_ferret.each do |record| |
|---|
| 225 |
assert ActsAsFerret::FerretResult === record, record.inspect |
|---|
| 226 |
assert !record.description.blank? |
|---|
| 227 |
assert_nil record.instance_variable_get(:"@ar_record") |
|---|
| 228 |
end |
|---|
| 229 |
end |
|---|
| 230 |
|
|---|
| 231 |
def test_find_ids |
|---|
| 232 |
assert_equal 4, ContentBase.find(:all).size |
|---|
| 233 |
|
|---|
| 234 |
[ 'title:title OR description:title OR content:title', 'title', '*:title'].each do |query| |
|---|
| 235 |
total_hits, contents_from_ferret = ActsAsFerret.find_ids(query, Content) |
|---|
| 236 |
assert_equal 2, contents_from_ferret.size, query |
|---|
| 237 |
assert_equal 2, total_hits, query |
|---|
| 238 |
assert_equal contents(:first).id, contents_from_ferret.first[:id].to_i |
|---|
| 239 |
assert_equal @another_content.id, contents_from_ferret.last[:id].to_i |
|---|
| 240 |
end |
|---|
| 241 |
|
|---|
| 242 |
ContentBase.rebuild_index |
|---|
| 243 |
Comment.rebuild_index |
|---|
| 244 |
['title OR comment', 'title:(title OR comment) OR description:(title OR comment) OR content:(title OR comment)'].each do |query| |
|---|
| 245 |
total_hits, contents_from_ferret = ActsAsFerret.find_ids(query, [Comment, Content]) |
|---|
| 246 |
assert_equal 5, contents_from_ferret.size, query |
|---|
| 247 |
assert_equal 5, total_hits |
|---|
| 248 |
end |
|---|
| 249 |
end |
|---|
| 250 |
|
|---|
| 251 |
def test_find_ids_lazy |
|---|
| 252 |
total_hits, contents_from_ferret = ActsAsFerret.find_ids('title', [Comment, Content], :lazy => true) |
|---|
| 253 |
assert_equal 2, contents_from_ferret.size |
|---|
| 254 |
assert_equal 2, total_hits |
|---|
| 255 |
found = 0 |
|---|
| 256 |
contents_from_ferret.each do |data| |
|---|
| 257 |
next if data[:model] != 'Content' |
|---|
| 258 |
found += 1 |
|---|
| 259 |
assert !data[:data][:description].blank? |
|---|
| 260 |
end |
|---|
| 261 |
assert_equal 2, found |
|---|
| 262 |
end |
|---|
| 263 |
|
|---|
| 264 |
def test_pagination |
|---|
| 265 |
more_contents(true) |
|---|
| 266 |
|
|---|
| 267 |
r = ActsAsFerret.find 'title OR comment', [ Content, Comment ], :per_page => 10, :sort => 'title' |
|---|
| 268 |
assert_equal 60, r.total_hits |
|---|
| 269 |
assert_equal 10, r.size |
|---|
| 270 |
assert_equal "0", r.first.description |
|---|
| 271 |
assert_equal "9", r.last.description |
|---|
| 272 |
assert_equal 1, r.current_page |
|---|
| 273 |
assert_equal 6, r.page_count |
|---|
| 274 |
|
|---|
| 275 |
r = ActsAsFerret.find 'title OR comment', [ Content, Comment ], :page => '2', :per_page => 10, :sort => 'title' |
|---|
| 276 |
assert_equal 60, r.total_hits |
|---|
| 277 |
assert_equal 10, r.size |
|---|
| 278 |
assert_equal "10", r.first.description |
|---|
| 279 |
assert_equal "19", r.last.description |
|---|
| 280 |
assert_equal 2, r.current_page |
|---|
| 281 |
assert_equal 6, r.page_count |
|---|
| 282 |
|
|---|
| 283 |
r = ActsAsFerret.find 'title OR comment', [ Content, Comment ], :page => 7, :per_page => 10, :sort => 'title' |
|---|
| 284 |
assert_equal 60, r.total_hits |
|---|
| 285 |
assert_equal 0, r.size |
|---|
| 286 |
end |
|---|
| 287 |
|
|---|
| 288 |
def test_pagination_with_ar_conditions |
|---|
| 289 |
more_contents(true) |
|---|
| 290 |
id = Content.find_with_ferret('title').first.id |
|---|
| 291 |
r = ActsAsFerret.find 'title OR comment', [Content, Comment], { :page => 1, :per_page => 10 }, |
|---|
| 292 |
{ :conditions => { :content => ["id != ?", id] }, :order => 'id ASC' } |
|---|
| 293 |
assert_equal 59, r.total_hits |
|---|
| 294 |
assert_equal 10, r.size |
|---|
| 295 |
assert_equal "Comment for content 00", r.first.content |
|---|
| 296 |
assert_equal "Comment for content 09", r.last.content |
|---|
| 297 |
assert_equal 1, r.current_page |
|---|
| 298 |
assert_equal 6, r.page_count |
|---|
| 299 |
|
|---|
| 300 |
r = ActsAsFerret.find 'title OR comment', [Content, Comment], { :page => 6, :per_page => 10 }, |
|---|
| 301 |
{ :conditions => { :content => [ "id != ?", id ] }, :order => 'id ASC' } |
|---|
| 302 |
assert_equal 59, r.total_hits |
|---|
| 303 |
assert_equal 9, r.size |
|---|
| 304 |
assert_equal "21", r.first.description |
|---|
| 305 |
assert_equal "29", r.last.description |
|---|
| 306 |
assert_equal 6, r.current_page |
|---|
| 307 |
assert_equal 6, r.page_count |
|---|
| 308 |
end |
|---|
| 309 |
|
|---|
| 310 |
protected |
|---|
| 311 |
|
|---|
| 312 |
def more_contents(with_comments = false) |
|---|
| 313 |
Comment.destroy_all if with_comments |
|---|
| 314 |
Content.destroy_all |
|---|
| 315 |
SpecialContent.destroy_all |
|---|
| 316 |
30.times do |i| |
|---|
| 317 |
c = Content.create! :title => sprintf("title of Content %02d", i), :description => "#{i}" |
|---|
| 318 |
c.comments.create! :content => sprintf("Comment for content %02d", i) if with_comments |
|---|
| 319 |
end |
|---|
| 320 |
end |
|---|
| 321 |
|
|---|
| 322 |
def remove_index(clazz) |
|---|
| 323 |
clazz.aaf_index.close # avoid io error when deleting the open index |
|---|
| 324 |
FileUtils.rm_rf clazz.aaf_configuration[:index_dir] |
|---|
| 325 |
assert !File.exists?("#{clazz.aaf_configuration[:index_dir]}/segments") |
|---|
| 326 |
end |
|---|
| 327 |
|
|---|
| 328 |
end |
|---|
| 329 |
|
|---|