cehoffman-acts_as_ferret 0.4.4
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.
- data/LICENSE +20 -0
- data/README +68 -0
- data/bin/aaf_install +23 -0
- data/config/ferret_server.yml +24 -0
- data/doc/README.win32 +23 -0
- data/doc/demo/README +154 -0
- data/doc/demo/README_DEMO +23 -0
- data/doc/demo/Rakefile +10 -0
- data/doc/demo/app/controllers/admin/backend_controller.rb +14 -0
- data/doc/demo/app/controllers/admin_area_controller.rb +4 -0
- data/doc/demo/app/controllers/application.rb +5 -0
- data/doc/demo/app/controllers/contents_controller.rb +49 -0
- data/doc/demo/app/controllers/searches_controller.rb +8 -0
- data/doc/demo/app/helpers/admin/backend_helper.rb +2 -0
- data/doc/demo/app/helpers/application_helper.rb +3 -0
- data/doc/demo/app/helpers/content_helper.rb +2 -0
- data/doc/demo/app/helpers/search_helper.rb +2 -0
- data/doc/demo/app/models/comment.rb +48 -0
- data/doc/demo/app/models/content.rb +12 -0
- data/doc/demo/app/models/content_base.rb +28 -0
- data/doc/demo/app/models/search.rb +19 -0
- data/doc/demo/app/models/shared_index1.rb +3 -0
- data/doc/demo/app/models/shared_index2.rb +3 -0
- data/doc/demo/app/models/special_content.rb +3 -0
- data/doc/demo/app/models/stats.rb +20 -0
- data/doc/demo/app/views/admin/backend/search.rhtml +18 -0
- data/doc/demo/app/views/contents/_form.rhtml +10 -0
- data/doc/demo/app/views/contents/edit.rhtml +9 -0
- data/doc/demo/app/views/contents/index.rhtml +24 -0
- data/doc/demo/app/views/contents/new.rhtml +8 -0
- data/doc/demo/app/views/contents/show.rhtml +8 -0
- data/doc/demo/app/views/layouts/application.html.erb +17 -0
- data/doc/demo/app/views/searches/_content.html.erb +2 -0
- data/doc/demo/app/views/searches/search.html.erb +20 -0
- data/doc/demo/config/boot.rb +109 -0
- data/doc/demo/config/database.yml +38 -0
- data/doc/demo/config/environment.rb +69 -0
- data/doc/demo/config/environments/development.rb +16 -0
- data/doc/demo/config/environments/production.rb +19 -0
- data/doc/demo/config/environments/test.rb +21 -0
- data/doc/demo/config/ferret_server.yml +18 -0
- data/doc/demo/config/lighttpd.conf +40 -0
- data/doc/demo/config/routes.rb +9 -0
- data/doc/demo/db/development_structure.sql +15 -0
- data/doc/demo/db/migrate/001_initial_migration.rb +18 -0
- data/doc/demo/db/migrate/002_add_type_to_contents.rb +9 -0
- data/doc/demo/db/migrate/003_create_shared_index1s.rb +11 -0
- data/doc/demo/db/migrate/004_create_shared_index2s.rb +11 -0
- data/doc/demo/db/migrate/005_special_field.rb +9 -0
- data/doc/demo/db/migrate/006_create_stats.rb +15 -0
- data/doc/demo/db/schema.sql +18 -0
- data/doc/demo/doc/README_FOR_APP +2 -0
- data/doc/demo/doc/howto.txt +70 -0
- data/doc/demo/public/.htaccess +40 -0
- data/doc/demo/public/404.html +8 -0
- data/doc/demo/public/500.html +8 -0
- data/doc/demo/public/dispatch.cgi +10 -0
- data/doc/demo/public/dispatch.fcgi +24 -0
- data/doc/demo/public/dispatch.rb +10 -0
- data/doc/demo/public/favicon.ico +0 -0
- data/doc/demo/public/images/rails.png +0 -0
- data/doc/demo/public/index.html +277 -0
- data/doc/demo/public/robots.txt +1 -0
- data/doc/demo/public/stylesheets/scaffold.css +74 -0
- data/doc/demo/script/about +3 -0
- data/doc/demo/script/breakpointer +3 -0
- data/doc/demo/script/console +3 -0
- data/doc/demo/script/destroy +3 -0
- data/doc/demo/script/ferret_server +10 -0
- data/doc/demo/script/generate +3 -0
- data/doc/demo/script/performance/benchmarker +3 -0
- data/doc/demo/script/performance/profiler +3 -0
- data/doc/demo/script/plugin +3 -0
- data/doc/demo/script/process/inspector +3 -0
- data/doc/demo/script/process/reaper +3 -0
- data/doc/demo/script/process/spawner +3 -0
- data/doc/demo/script/process/spinner +3 -0
- data/doc/demo/script/runner +3 -0
- data/doc/demo/script/server +3 -0
- data/doc/demo/test/fixtures/comments.yml +12 -0
- data/doc/demo/test/fixtures/contents.yml +13 -0
- data/doc/demo/test/fixtures/remote_contents.yml +9 -0
- data/doc/demo/test/fixtures/shared_index1s.yml +7 -0
- data/doc/demo/test/fixtures/shared_index2s.yml +7 -0
- data/doc/demo/test/functional/admin/backend_controller_test.rb +35 -0
- data/doc/demo/test/functional/contents_controller_test.rb +81 -0
- data/doc/demo/test/functional/searches_controller_test.rb +71 -0
- data/doc/demo/test/smoke/drb_smoke_test.rb +321 -0
- data/doc/demo/test/smoke/process_stats.rb +21 -0
- data/doc/demo/test/test_helper.rb +30 -0
- data/doc/demo/test/unit/comment_test.rb +217 -0
- data/doc/demo/test/unit/content_test.rb +705 -0
- data/doc/demo/test/unit/ferret_result_test.rb +24 -0
- data/doc/demo/test/unit/multi_index_test.rb +329 -0
- data/doc/demo/test/unit/remote_index_test.rb +23 -0
- data/doc/demo/test/unit/shared_index1_test.rb +108 -0
- data/doc/demo/test/unit/shared_index2_test.rb +13 -0
- data/doc/demo/test/unit/sort_test.rb +21 -0
- data/doc/demo/test/unit/special_content_test.rb +25 -0
- data/doc/demo/vendor/plugins/will_paginate/LICENSE +18 -0
- data/doc/demo/vendor/plugins/will_paginate/README +108 -0
- data/doc/demo/vendor/plugins/will_paginate/Rakefile +23 -0
- data/doc/demo/vendor/plugins/will_paginate/init.rb +21 -0
- data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/collection.rb +45 -0
- data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/core_ext.rb +44 -0
- data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/finder.rb +159 -0
- data/doc/demo/vendor/plugins/will_paginate/lib/will_paginate/view_helpers.rb +95 -0
- data/doc/demo/vendor/plugins/will_paginate/test/array_pagination_test.rb +23 -0
- data/doc/demo/vendor/plugins/will_paginate/test/boot.rb +27 -0
- data/doc/demo/vendor/plugins/will_paginate/test/console +10 -0
- data/doc/demo/vendor/plugins/will_paginate/test/finder_test.rb +219 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/admin.rb +3 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/companies.yml +24 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/company.rb +23 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/developer.rb +11 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/developers_projects.yml +13 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/project.rb +4 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/projects.yml +7 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/replies.yml +20 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/reply.rb +5 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/schema.sql +44 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/topic.rb +19 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/topics.yml +30 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/user.rb +2 -0
- data/doc/demo/vendor/plugins/will_paginate/test/fixtures/users.yml +35 -0
- data/doc/demo/vendor/plugins/will_paginate/test/helper.rb +42 -0
- data/doc/demo/vendor/plugins/will_paginate/test/lib/activerecord_test_connector.rb +64 -0
- data/doc/demo/vendor/plugins/will_paginate/test/lib/load_fixtures.rb +10 -0
- data/doc/demo/vendor/plugins/will_paginate/test/pagination_test.rb +136 -0
- data/doc/monit-example +22 -0
- data/init.rb +24 -0
- data/install.rb +18 -0
- data/lib/act_methods.rb +147 -0
- data/lib/acts_as_ferret.rb +584 -0
- data/lib/ar_mysql_auto_reconnect_patch.rb +41 -0
- data/lib/blank_slate.rb +53 -0
- data/lib/bulk_indexer.rb +38 -0
- data/lib/class_methods.rb +270 -0
- data/lib/ferret_extensions.rb +188 -0
- data/lib/ferret_find_methods.rb +141 -0
- data/lib/ferret_result.rb +53 -0
- data/lib/ferret_server.rb +238 -0
- data/lib/index.rb +99 -0
- data/lib/instance_methods.rb +171 -0
- data/lib/local_index.rb +205 -0
- data/lib/more_like_this.rb +217 -0
- data/lib/multi_index.rb +126 -0
- data/lib/rdig_adapter.rb +148 -0
- data/lib/remote_functions.rb +23 -0
- data/lib/remote_index.rb +54 -0
- data/lib/remote_multi_index.rb +20 -0
- data/lib/search_results.rb +50 -0
- data/lib/server_manager.rb +58 -0
- data/lib/unix_daemon.rb +64 -0
- data/lib/without_ar.rb +52 -0
- data/rakefile +141 -0
- data/recipes/aaf_recipes.rb +114 -0
- data/script/ferret_daemon +94 -0
- data/script/ferret_server +10 -0
- data/script/ferret_service +178 -0
- data/tasks/ferret.rake +22 -0
- metadata +258 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'gruff'
|
|
3
|
+
|
|
4
|
+
search = Stats.compute :search
|
|
5
|
+
write = Stats.compute :write
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
g = chart "aaf DRb (write performance)"
|
|
9
|
+
g.data :avg, write.map{|r| r[:avg]}
|
|
10
|
+
g.data :stddev, write.map{|r| r[:stddev]}
|
|
11
|
+
g.write "write_averages.png"
|
|
12
|
+
|
|
13
|
+
g = chart "aaf DRb (search performance)"
|
|
14
|
+
g.data :average, search.map{ |r| r[:avg] }
|
|
15
|
+
g.data :stddev, search.map{ |r| r[:stddev] }
|
|
16
|
+
g.write "search_averages.png"
|
|
17
|
+
|
|
18
|
+
g = chart "aaf DRb (search performance (medians))"
|
|
19
|
+
g.data :search_median, search.map{ |r| r[:median] }
|
|
20
|
+
g.write "search_medians.png"
|
|
21
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
|
|
3
|
+
require 'test_help'
|
|
4
|
+
|
|
5
|
+
class Test::Unit::TestCase
|
|
6
|
+
# Transactional fixtures accelerate your tests by wrapping each test method
|
|
7
|
+
# in a transaction that's rolled back on completion. This ensures that the
|
|
8
|
+
# test database remains unchanged so your fixtures don't have to be reloaded
|
|
9
|
+
# between every test method. Fewer database queries means faster tests.
|
|
10
|
+
#
|
|
11
|
+
# Read Mike Clark's excellent walkthrough at
|
|
12
|
+
# http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
|
|
13
|
+
#
|
|
14
|
+
# Every Active Record database supports transactions except MyISAM tables
|
|
15
|
+
# in MySQL. Turn off transactional fixtures in this case; however, if you
|
|
16
|
+
# don't care one way or the other, switching from MyISAM to InnoDB tables
|
|
17
|
+
# is recommended.
|
|
18
|
+
#self.use_transactional_fixtures = true
|
|
19
|
+
self.use_transactional_fixtures = false
|
|
20
|
+
|
|
21
|
+
# Instantiated fixtures are slow, but give you @david where otherwise you
|
|
22
|
+
# would need people(:david). If you don't want to migrate your existing
|
|
23
|
+
# test cases which use the @david style and don't mind the speed hit (each
|
|
24
|
+
# instantiated fixtures translates to a database query per test method),
|
|
25
|
+
# then set this back to true.
|
|
26
|
+
self.use_instantiated_fixtures = false
|
|
27
|
+
|
|
28
|
+
# Add more helper methods to be used by all tests here...
|
|
29
|
+
end
|
|
30
|
+
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
|
2
|
+
|
|
3
|
+
class CommentTest < Test::Unit::TestCase
|
|
4
|
+
fixtures :comments
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
Comment.rebuild_index
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Replace this with your real tests.
|
|
11
|
+
def test_truth
|
|
12
|
+
assert_kind_of Comment, comments(:first)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_issue_220_index_false_as_false
|
|
16
|
+
c = Comment.new :content => false
|
|
17
|
+
assert_equal false, c.content
|
|
18
|
+
assert_equal 'false', c.content_for_field_name(:content)
|
|
19
|
+
assert_equal 'false', c.to_doc[:content]
|
|
20
|
+
c.save
|
|
21
|
+
assert_equal c, Comment.find_with_ferret('content:false').first
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_if_option
|
|
25
|
+
c = Comment.new :content => 'do not index'
|
|
26
|
+
c.save
|
|
27
|
+
assert_equal 0, Comment.find_with_ferret('do not index').total_hits
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_analyzer
|
|
31
|
+
c = Comment.create! :content => 'a fax modem'
|
|
32
|
+
assert_equal 0, Comment.find_with_ferret('fax').size
|
|
33
|
+
assert_equal 1, Comment.find_with_ferret('modem').size
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_class_index_dir
|
|
37
|
+
assert Comment.aaf_configuration[:index_dir] =~ %r{^#{RAILS_ROOT}/index/test/comment}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_aliased_field
|
|
41
|
+
res = Comment.find_with_ferret 'aliased:regarding'
|
|
42
|
+
assert_equal 1, res.total_hits
|
|
43
|
+
assert_equal comments(:comment_for_c2), res.first
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_search_for_id
|
|
47
|
+
# don't search the id field by default:
|
|
48
|
+
assert Comment.find_with_ferret('3').empty?
|
|
49
|
+
# explicit query for id field works:
|
|
50
|
+
assert_equal 3, Comment.find_with_ferret('id:3').first.id
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#def test_reloadable
|
|
54
|
+
# assert ! Comment.reloadable?
|
|
55
|
+
#end
|
|
56
|
+
|
|
57
|
+
# tests the automatic building of an index when none exists
|
|
58
|
+
# delete index/test/* before running rake to make this useful
|
|
59
|
+
def test_automatic_index_build
|
|
60
|
+
# TODO: check why this fails, but querying for 'comment fixture' works.
|
|
61
|
+
# maybe different analyzers at index creation and searching time ?
|
|
62
|
+
#comments_from_ferret = Comment.find_with_ferret('"comment from fixture"')
|
|
63
|
+
comments_from_ferret = Comment.find_with_ferret('comment fixture')
|
|
64
|
+
assert_equal 2, comments_from_ferret.size
|
|
65
|
+
assert comments_from_ferret.include?(comments(:first))
|
|
66
|
+
assert comments_from_ferret.include?(comments(:another))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_rebuild_index
|
|
70
|
+
Comment.aaf_index.ferret_index.query_delete('comment')
|
|
71
|
+
comments_from_ferret = Comment.find_with_ferret('comment AND fixture')
|
|
72
|
+
assert comments_from_ferret.empty?
|
|
73
|
+
Comment.rebuild_index
|
|
74
|
+
comments_from_ferret = Comment.find_with_ferret('comment AND fixture')
|
|
75
|
+
assert_equal 2, comments_from_ferret.size
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_total_hits
|
|
79
|
+
comments_from_ferret = Comment.find_with_ferret('comment AND fixture', :limit => 1)
|
|
80
|
+
assert_equal 1, comments_from_ferret.size
|
|
81
|
+
assert_equal 2, comments_from_ferret.total_hits
|
|
82
|
+
|
|
83
|
+
comments_from_ferret = Comment.find_with_ferret('comment AND fixture', {}, :conditions => 'id != 1')
|
|
84
|
+
assert_equal 1, comments_from_ferret.size
|
|
85
|
+
assert_equal 1, comments_from_ferret.total_hits
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_score
|
|
89
|
+
comments_from_ferret = Comment.find_with_ferret('comment AND fixture', :limit => 1)
|
|
90
|
+
assert comments_from_ferret.first
|
|
91
|
+
assert comments_from_ferret.first.ferret_score > 0
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_find_all
|
|
95
|
+
20.times do |i|
|
|
96
|
+
Comment.create( :author => 'multi-commenter', :content => "This is multicomment no #{i}" )
|
|
97
|
+
end
|
|
98
|
+
assert_equal 10, (res = Comment.find_with_ferret('multicomment')).size
|
|
99
|
+
assert_equal 20, res.total_hits
|
|
100
|
+
assert_equal 15, (res = Comment.find_with_ferret('multicomment', :limit => 15)).size
|
|
101
|
+
assert_equal 20, res.total_hits
|
|
102
|
+
assert_equal 20, (res = Comment.find_with_ferret('multicomment', :limit => :all)).size
|
|
103
|
+
assert_equal 20, res.total_hits
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# tests the custom to_doc method defined in comment.rb
|
|
107
|
+
def test_custom_to_doc
|
|
108
|
+
top_docs = Comment.aaf_index.ferret_index.search('"from fixture"')
|
|
109
|
+
#top_docs = Comment.ferret_index.search('"comment from fixture"')
|
|
110
|
+
assert_equal 2, top_docs.total_hits
|
|
111
|
+
doc = Comment.aaf_index.ferret_index.doc(top_docs.hits[0].doc)
|
|
112
|
+
# check for the special field added by the custom to_doc method
|
|
113
|
+
assert_not_nil doc[:added]
|
|
114
|
+
# still a valid int ?
|
|
115
|
+
assert doc[:added].to_i > 0
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def test_find_with_ferret
|
|
119
|
+
comment = Comment.create( :author => 'john doe', :content => 'This is a useless comment' )
|
|
120
|
+
comment2 = Comment.create( :author => 'another', :content => 'content' )
|
|
121
|
+
|
|
122
|
+
comments_from_ferret = Comment.find_with_ferret('anoth* OR jo*')
|
|
123
|
+
assert_equal 2, comments_from_ferret.size
|
|
124
|
+
assert comments_from_ferret.include?(comment)
|
|
125
|
+
assert comments_from_ferret.include?(comment2)
|
|
126
|
+
|
|
127
|
+
# find options
|
|
128
|
+
comments_from_ferret = Comment.find_with_ferret('anoth* OR jo*', {}, :conditions => ["id=?",comment2.id])
|
|
129
|
+
assert_equal 1, comments_from_ferret.size
|
|
130
|
+
assert comments_from_ferret.include?(comment2)
|
|
131
|
+
|
|
132
|
+
comments_from_ferret = Comment.find_with_ferret('lorem ipsum not here')
|
|
133
|
+
assert comments_from_ferret.empty?
|
|
134
|
+
|
|
135
|
+
comments_from_ferret = Comment.find_with_ferret('another')
|
|
136
|
+
assert_equal 1, comments_from_ferret.size
|
|
137
|
+
assert_equal comment2.id, comments_from_ferret.first.id
|
|
138
|
+
|
|
139
|
+
comments_from_ferret = Comment.find_with_ferret('doe')
|
|
140
|
+
assert_equal 1, comments_from_ferret.size
|
|
141
|
+
assert_equal comment.id, comments_from_ferret.first.id
|
|
142
|
+
|
|
143
|
+
comments_from_ferret = Comment.find_with_ferret('useless')
|
|
144
|
+
assert_equal 1, comments_from_ferret.size
|
|
145
|
+
assert_equal comment.id, comments_from_ferret.first.id
|
|
146
|
+
|
|
147
|
+
# no monkeys here
|
|
148
|
+
comments_from_ferret = Comment.find_with_ferret('monkey')
|
|
149
|
+
assert comments_from_ferret.empty?
|
|
150
|
+
|
|
151
|
+
# multiple terms are ANDed by default...
|
|
152
|
+
comments_from_ferret = Comment.find_with_ferret('monkey comment')
|
|
153
|
+
assert comments_from_ferret.empty?
|
|
154
|
+
# ...unless you connect them by OR
|
|
155
|
+
comments_from_ferret = Comment.find_with_ferret('monkey OR comment')
|
|
156
|
+
assert_equal 3, comments_from_ferret.size
|
|
157
|
+
assert comments_from_ferret.include?(comment)
|
|
158
|
+
assert comments_from_ferret.include?(comments(:first))
|
|
159
|
+
assert comments_from_ferret.include?(comments(:another))
|
|
160
|
+
|
|
161
|
+
# multiple terms, each term has to occur in a document to be found,
|
|
162
|
+
# but they may occur in different fields
|
|
163
|
+
comments_from_ferret = Comment.find_with_ferret('useless john')
|
|
164
|
+
assert_equal 1, comments_from_ferret.size
|
|
165
|
+
assert_equal comment.id, comments_from_ferret.first.id
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# search for an exact string by enclosing it in "
|
|
169
|
+
comments_from_ferret = Comment.find_with_ferret('"useless john"')
|
|
170
|
+
assert comments_from_ferret.empty?
|
|
171
|
+
comments_from_ferret = Comment.find_with_ferret('"useless comment"')
|
|
172
|
+
assert_equal 1, comments_from_ferret.size
|
|
173
|
+
assert_equal comment.id, comments_from_ferret.first.id
|
|
174
|
+
|
|
175
|
+
comment.destroy
|
|
176
|
+
comment2.destroy
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# fixed with Ferret 0.9.6
|
|
180
|
+
def test_stopwords_ferret_bug
|
|
181
|
+
i = Ferret::I.new(:or_default => false, :default_field => '*' )
|
|
182
|
+
d = Ferret::Document.new
|
|
183
|
+
d[:id] = '1'
|
|
184
|
+
d[:content] = 'Move or shake'
|
|
185
|
+
i << d
|
|
186
|
+
hits = i.search 'move AND or AND shake'
|
|
187
|
+
assert_equal 1, hits.total_hits
|
|
188
|
+
hits = i.search 'move AND nothere AND shake'
|
|
189
|
+
assert_equal 0, hits.total_hits
|
|
190
|
+
hits = i.search 'move AND shake'
|
|
191
|
+
assert_equal 1, hits.total_hits
|
|
192
|
+
hits = i.search 'move OR shake'
|
|
193
|
+
assert_equal 1, hits.total_hits
|
|
194
|
+
hits = i.search '+move +the +shake'
|
|
195
|
+
assert_equal 1, hits.total_hits
|
|
196
|
+
|
|
197
|
+
hits = i.search 'move nothere'
|
|
198
|
+
assert_equal 0, hits.total_hits
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def test_stopwords
|
|
202
|
+
comment = Comment.create( :author => 'john doe', :content => 'Move or shake' )
|
|
203
|
+
['move shake', 'Move shake', 'move Shake', 'move or shake', 'move the shake'].each do |q|
|
|
204
|
+
comments_from_ferret = Comment.find_with_ferret(q)
|
|
205
|
+
assert_equal comment, comments_from_ferret.first, "query #{q} failed"
|
|
206
|
+
end
|
|
207
|
+
comment.destroy
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def test_array_conditions_combining
|
|
211
|
+
comments_from_ferret = Comment.find_with_ferret('comment AND fixture', {}, :conditions => [ 'id IN (?)', [ 2, 3 ] ])
|
|
212
|
+
assert_equal 1, comments_from_ferret.size
|
|
213
|
+
assert_equal 1, comments_from_ferret.total_hits
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
end
|
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
|
2
|
+
require 'pp'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
class ContentTest < 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
|
+
def test_limit_all
|
|
31
|
+
res = Content.find_with_ferret '*', { :limit => :all }, :conditions => ['lower(title) like ?', 'content'], :order => 'contents.description'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_find_with_ferret_on_has_many_assoc
|
|
35
|
+
c = contents(:first)
|
|
36
|
+
comments = c.comments.find_with_ferret 'second'
|
|
37
|
+
assert_equal 1, comments.size
|
|
38
|
+
assert_equal comments(:another), comments.first
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_total_hits_on_has_many_assoc
|
|
42
|
+
c = contents(:first)
|
|
43
|
+
assert_equal 2, Comment.find_with_ferret('second OR regarding').total_hits
|
|
44
|
+
assert_equal 1, c.comments.find_with_ferret('second OR regarding').total_hits
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_include_option
|
|
48
|
+
assert_equal 1, Content.find_with_ferret('description', {}, :include => :comments).size
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_lazy_loading
|
|
52
|
+
results = Content.find_with_ferret 'description', :lazy => true
|
|
53
|
+
assert_equal 1, results.size
|
|
54
|
+
result = results.first
|
|
55
|
+
class << result
|
|
56
|
+
attr_accessor :ar_record # so we have a chance to check if it's been loaded...
|
|
57
|
+
end
|
|
58
|
+
assert ActsAsFerret::FerretResult === result
|
|
59
|
+
assert_equal 'A useless description', result.description
|
|
60
|
+
assert_nil result.instance_variable_get(:@ar_record)
|
|
61
|
+
assert_equal 'My Title', result.title
|
|
62
|
+
assert_not_nil result.ar_record
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def test_ticket_69
|
|
66
|
+
content = Content.create(:title => 'aksjeselskap test',
|
|
67
|
+
:description => 'content about various norwegian companies. A.s. Haakon, Åmot Håndverksenter A/S, Øye Trelast AS')
|
|
68
|
+
|
|
69
|
+
# these still fail: 'A\S', 'AS'
|
|
70
|
+
[ '"A.s. Haakon"', 'A.s. Haakon', 'Åmot A/S', 'A/S' ].each do |query|
|
|
71
|
+
assert_equal content, Content.find_with_ferret(query).first, query
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_highlight
|
|
76
|
+
highlight = @another_content.highlight('title')
|
|
77
|
+
assert_equal 1, highlight.size
|
|
78
|
+
assert_equal "this is not the <em>title</em>", highlight.first
|
|
79
|
+
|
|
80
|
+
highlight = @another_content.highlight('title', :field => :description)
|
|
81
|
+
assert_equal 1, highlight.size
|
|
82
|
+
assert_equal "this is not the <em>title</em>", highlight.first
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def test_highlight_new_record
|
|
86
|
+
c = Content.create :title => 'the title', :description => 'the new description'
|
|
87
|
+
highlight = c.highlight('new')
|
|
88
|
+
assert_equal 1, highlight.size
|
|
89
|
+
assert_equal "the <em>new</em> description", highlight.first
|
|
90
|
+
|
|
91
|
+
c1 = Content.find_with_ferret('new description').first
|
|
92
|
+
assert_equal c, c1
|
|
93
|
+
highlight = c1.highlight('new')
|
|
94
|
+
assert_equal 1, highlight.size
|
|
95
|
+
assert_equal "the <em>new</em> description", highlight.first
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def test_disable_ferret_once
|
|
99
|
+
content = Content.new(:title => 'should not get saved', :description => 'do not find me')
|
|
100
|
+
assert_raises (ArgumentError) do
|
|
101
|
+
content.disable_ferret(:wrong)
|
|
102
|
+
end
|
|
103
|
+
assert content.ferret_enabled?
|
|
104
|
+
content.disable_ferret
|
|
105
|
+
assert !content.ferret_enabled?
|
|
106
|
+
content.save
|
|
107
|
+
assert content.ferret_enabled?
|
|
108
|
+
assert Content.find_with_ferret('"find me"').empty?
|
|
109
|
+
|
|
110
|
+
content.save
|
|
111
|
+
assert content.ferret_enabled?
|
|
112
|
+
assert_equal content, Content.find_with_ferret('"find me"').first
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_ferret_disable_always
|
|
116
|
+
content = Content.new(:title => 'should not get saved', :description => 'do not find me')
|
|
117
|
+
assert content.ferret_enabled?
|
|
118
|
+
content.disable_ferret(:always)
|
|
119
|
+
assert !content.ferret_enabled?
|
|
120
|
+
2.times do
|
|
121
|
+
content.save
|
|
122
|
+
assert Content.find_with_ferret('"find me"').empty?
|
|
123
|
+
assert !content.ferret_enabled?
|
|
124
|
+
end
|
|
125
|
+
content.ferret_enable
|
|
126
|
+
assert content.ferret_enabled?
|
|
127
|
+
content.save
|
|
128
|
+
assert content.ferret_enabled?
|
|
129
|
+
assert_equal content, Content.find_with_ferret('"find me"').first
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def test_disable_ferret_on_class_level
|
|
133
|
+
Content.disable_ferret
|
|
134
|
+
content = Content.new(:title => 'should not get saved', :description => 'do not find me')
|
|
135
|
+
assert !content.ferret_enabled?
|
|
136
|
+
assert !Content.ferret_enabled?
|
|
137
|
+
2.times do
|
|
138
|
+
content.save
|
|
139
|
+
assert Content.find_with_ferret('"find me"').empty?
|
|
140
|
+
assert !Content.ferret_enabled?
|
|
141
|
+
assert !content.ferret_enabled?
|
|
142
|
+
end
|
|
143
|
+
content.enable_ferret # record level enabling should have no effect on class level
|
|
144
|
+
assert !Content.ferret_enabled?
|
|
145
|
+
assert !content.ferret_enabled?
|
|
146
|
+
Content.enable_ferret
|
|
147
|
+
assert Content.ferret_enabled?
|
|
148
|
+
assert content.ferret_enabled?
|
|
149
|
+
|
|
150
|
+
content.save
|
|
151
|
+
assert content.ferret_enabled?
|
|
152
|
+
assert Content.ferret_enabled?
|
|
153
|
+
assert_equal content, Content.find_with_ferret('"find me"').first
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def test_disable_ferret_block
|
|
157
|
+
content = Content.new(:title => 'should not get saved', :description => 'do not find me')
|
|
158
|
+
content.disable_ferret do
|
|
159
|
+
2.times do
|
|
160
|
+
content.save
|
|
161
|
+
assert Content.find_with_ferret('"find me"').empty?
|
|
162
|
+
assert !content.ferret_enabled?
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
assert content.ferret_enabled?
|
|
166
|
+
assert Content.find_with_ferret('"find me"').empty?
|
|
167
|
+
|
|
168
|
+
content.disable_ferret(:index_when_finished) do
|
|
169
|
+
2.times do
|
|
170
|
+
content.save
|
|
171
|
+
assert Content.find_with_ferret('"find me"').empty?
|
|
172
|
+
assert !content.ferret_enabled?
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
assert content.ferret_enabled?
|
|
176
|
+
assert_equal content, Content.find_with_ferret('"find me"').first
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def test_disable_ferret_on_class_level_block
|
|
180
|
+
content = Content.new(:title => 'should not get saved', :description => 'do not find me')
|
|
181
|
+
Content.disable_ferret do
|
|
182
|
+
2.times do
|
|
183
|
+
content.save
|
|
184
|
+
assert Content.find_with_ferret('"find me"').empty?
|
|
185
|
+
assert !content.ferret_enabled?
|
|
186
|
+
assert !Content.ferret_enabled?
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
assert content.ferret_enabled?
|
|
190
|
+
assert Content.ferret_enabled?
|
|
191
|
+
assert Content.find_with_ferret('"find me"').empty?
|
|
192
|
+
content.save
|
|
193
|
+
assert_equal content, Content.find_with_ferret('"find me"').first
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# ticket 178
|
|
197
|
+
def test_records_for_rebuild_works_with_includes
|
|
198
|
+
size = Content.count
|
|
199
|
+
Content.send( :with_scope, :find => { :include => :comments } ) do
|
|
200
|
+
Content.records_for_rebuild do |records, offset|
|
|
201
|
+
assert_equal size, records.size
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def test_records_for_bulk_index
|
|
207
|
+
Content.disable_ferret do
|
|
208
|
+
more_contents
|
|
209
|
+
end
|
|
210
|
+
min = Content.find(:all, :order => 'id asc').first.id
|
|
211
|
+
Content.records_for_bulk_index([min, min+1, min+2, min+3, min+4, min+6], 10) do |records, offset|
|
|
212
|
+
assert_equal 6, records.size
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def test_bulk_index_no_optimize
|
|
217
|
+
Content.disable_ferret do
|
|
218
|
+
more_contents
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
assert Content.find_with_ferret('title').empty?
|
|
222
|
+
min = Content.find(:all, :order => 'id asc').first.id
|
|
223
|
+
Content.bulk_index(min, min+1, min+2, min+3, min+4, min+6, :optimize => false)
|
|
224
|
+
assert_equal 6, Content.find_with_ferret('title').size
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def test_bulk_index
|
|
228
|
+
Content.disable_ferret do
|
|
229
|
+
more_contents
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
assert Content.find_with_ferret('title').empty?
|
|
233
|
+
min = Content.find(:all, :order => 'id asc').first.id
|
|
234
|
+
Content.bulk_index([min, min+1, min+2, min+3, min+4, min+6])
|
|
235
|
+
assert_equal 6, Content.find_with_ferret('title').size
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def test_unicode
|
|
240
|
+
content = Content.new(:title => 'Title with some Ümläuts - äöü',
|
|
241
|
+
:description => 'look - an ß')
|
|
242
|
+
content.save
|
|
243
|
+
result = Content.find_with_ferret('äöü')
|
|
244
|
+
assert_equal content, result.first
|
|
245
|
+
result = Content.find_with_ferret('üml*')
|
|
246
|
+
assert_equal content, result.first
|
|
247
|
+
result = Content.find_with_ferret('ß')
|
|
248
|
+
assert_equal content, result.first
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def test_content_for_field_name
|
|
252
|
+
c = 'lorem ipsum dolor sit amet. lorem.'
|
|
253
|
+
@c1 = Content.new( :title => 'Content item 1',
|
|
254
|
+
:description => c )
|
|
255
|
+
assert_equal c, @c1.content_for_field_name(:description)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def test_document_number
|
|
259
|
+
c = 'lorem ipsum dolor sit amet. lorem.'
|
|
260
|
+
c1 = Content.new( :title => 'Content item 1',
|
|
261
|
+
:description => c )
|
|
262
|
+
c1.save
|
|
263
|
+
fi = Content.aaf_index.ferret_index
|
|
264
|
+
assert fi
|
|
265
|
+
hits = fi.search('title:"Content item 1"')
|
|
266
|
+
assert_equal 1, hits.total_hits
|
|
267
|
+
expected_doc_num = hits.hits.first.doc
|
|
268
|
+
assert_equal c, fi[expected_doc_num][:description]
|
|
269
|
+
doc_num = c1.document_number
|
|
270
|
+
assert_equal expected_doc_num, doc_num
|
|
271
|
+
assert_equal c, fi[doc_num][:description]
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def test_more_like_this
|
|
275
|
+
assert Content.find_with_ferret('lorem ipsum').empty?
|
|
276
|
+
@c1 = Content.new( :title => 'Content item 1',
|
|
277
|
+
:description => 'lorem ipsum dolor sit amet. lorem.' )
|
|
278
|
+
@c1.save
|
|
279
|
+
@c2 = Content.new( :title => 'Content item 2',
|
|
280
|
+
:description => 'lorem ipsum dolor sit amet. lorem ipsum.' )
|
|
281
|
+
@c2.save
|
|
282
|
+
assert_equal 2, Content.find_with_ferret('lorem ipsum').size
|
|
283
|
+
similar = @c1.more_like_this(:field_names => [:description], :min_doc_freq => 1, :min_term_freq => 1)
|
|
284
|
+
assert_equal 1, similar.size
|
|
285
|
+
assert_equal @c2, similar.first
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def test_more_like_this_new_record
|
|
289
|
+
assert Content.find_with_ferret('lorem ipsum').empty?
|
|
290
|
+
@c1 = Content.new( :title => 'Content item 1',
|
|
291
|
+
:description => 'lorem ipsum dolor sit amet. lorem.' )
|
|
292
|
+
@c2 = Content.new( :title => 'Content item 2',
|
|
293
|
+
:description => 'lorem ipsum dolor sit amet. lorem ipsum.' )
|
|
294
|
+
@c2.save
|
|
295
|
+
assert_equal 1, Content.find_with_ferret('lorem ipsum').size
|
|
296
|
+
similar = @c1.more_like_this(:field_names => [:description], :min_doc_freq => 1, :min_term_freq => 1)
|
|
297
|
+
assert_equal 1, similar.size
|
|
298
|
+
assert_equal @c2, similar.first
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def test_class_index_dir
|
|
302
|
+
assert Content.aaf_configuration[:index_dir] =~ %r{^#{RAILS_ROOT}/index/test/content_base}
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def test_update
|
|
306
|
+
contents_from_ferret = Content.find_with_ferret('useless')
|
|
307
|
+
assert_equal 1, contents_from_ferret.size
|
|
308
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
309
|
+
contents(:first).description = 'Updated description, still useless'
|
|
310
|
+
contents(:first).save
|
|
311
|
+
contents_from_ferret = Content.find_with_ferret('useless')
|
|
312
|
+
assert_equal 1, contents_from_ferret.size
|
|
313
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
314
|
+
contents_from_ferret = Content.find_with_ferret('updated AND description')
|
|
315
|
+
assert_equal 1, contents_from_ferret.size
|
|
316
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
317
|
+
contents_from_ferret = Content.find_with_ferret('updated OR description')
|
|
318
|
+
assert_equal 1, contents_from_ferret.size
|
|
319
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def test_indexed_method
|
|
323
|
+
assert_equal 2, @another_content.comment_count
|
|
324
|
+
assert_equal 2, contents(:first).comment_count
|
|
325
|
+
assert_equal 1, contents(:another).comment_count
|
|
326
|
+
# retrieve all content objects having 2 comments
|
|
327
|
+
result = Content.find_with_ferret('comment_count:2')
|
|
328
|
+
# TODO check why this range query returns 3 results
|
|
329
|
+
#result = Content.find_with_ferret('comment_count:[2 TO 1000]')
|
|
330
|
+
# p result
|
|
331
|
+
assert_equal 2, result.size
|
|
332
|
+
assert result.include?(@another_content)
|
|
333
|
+
assert result.include?(contents(:first))
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def test_sorting
|
|
337
|
+
sorting = [ Ferret::Search::SortField.new(:id, :reverse => true) ]
|
|
338
|
+
result = Content.find_with_ferret('comment_count:2', :sort => sorting)
|
|
339
|
+
assert !result.empty?
|
|
340
|
+
assert result.first.id > result.last.id
|
|
341
|
+
|
|
342
|
+
sorting = [ Ferret::Search::SortField.new(:id) ]
|
|
343
|
+
result = Content.find_with_ferret('comment_count:2', :sort => sorting)
|
|
344
|
+
assert result.first.id < result.last.id
|
|
345
|
+
|
|
346
|
+
sorting = Ferret::Search::Sort.new([ Ferret::Search::SortField.new(:id),
|
|
347
|
+
Ferret::Search::SortField::SCORE ],
|
|
348
|
+
:reverse => true)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
result = Content.find_with_ferret('comment_count:2', :sort => sorting)
|
|
352
|
+
assert result.first.id > result.last.id
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def test_sort_class
|
|
356
|
+
sorting = Ferret::Search::Sort.new(Ferret::Search::SortField.new(:id, :reverse => true))
|
|
357
|
+
result = Content.find_with_ferret('comment_count:2 OR comment_count:1', :sort => sorting)
|
|
358
|
+
assert result.size > 2
|
|
359
|
+
assert result.first.id > result.last.id
|
|
360
|
+
result = Content.find_with_ferret('comment_count:2 OR comment_count:1', :sort => sorting, :limit => 2)
|
|
361
|
+
assert_equal 2, result.size
|
|
362
|
+
assert result.first.id > result.last.id
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def test_sort_with_limit
|
|
366
|
+
sorting = [ Ferret::Search::SortField.new(:id) ]
|
|
367
|
+
result = Content.find_with_ferret('comment_count:2 OR comment_count:1', :sort => sorting)
|
|
368
|
+
assert result.size > 2
|
|
369
|
+
assert result.first.id < result.last.id
|
|
370
|
+
result = Content.find_with_ferret('comment_count:2 OR comment_count:1', :sort => sorting, :limit => 2)
|
|
371
|
+
assert_equal 2, result.size
|
|
372
|
+
assert result.first.id < result.last.id
|
|
373
|
+
|
|
374
|
+
sorting = [ Ferret::Search::SortField.new(:id, :reverse => true) ]
|
|
375
|
+
result = Content.find_with_ferret('comment_count:2 OR comment_count:1', :sort => sorting)
|
|
376
|
+
assert result.size > 2
|
|
377
|
+
assert result.first.id > result.last.id
|
|
378
|
+
result = Content.find_with_ferret('comment_count:2 OR comment_count:1', :sort => sorting, :limit => 2)
|
|
379
|
+
assert_equal 2, result.size
|
|
380
|
+
assert result.first.id > result.last.id
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def test_add_rebuilds_index
|
|
385
|
+
remove_index Content
|
|
386
|
+
Content.create(:title => 'another one', :description => 'description')
|
|
387
|
+
contents_from_ferret = Content.find_with_ferret('description:title')
|
|
388
|
+
assert_equal 1, contents_from_ferret.size
|
|
389
|
+
end
|
|
390
|
+
def test_find_rebuilds_index
|
|
391
|
+
remove_index Content
|
|
392
|
+
contents_from_ferret = Content.find_with_ferret('description:title')
|
|
393
|
+
assert_equal 1, contents_from_ferret.size
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def test_total_hits
|
|
397
|
+
assert_equal 2, Content.total_hits('title:title OR description:title')
|
|
398
|
+
assert_equal 2, Content.total_hits('title:title OR description:title', :limit => 1)
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def test_find_ids_with_ferret
|
|
402
|
+
total_hits, contents_from_ferret = Content.find_ids_with_ferret('title:title OR description:title')
|
|
403
|
+
assert_equal 2, contents_from_ferret.size
|
|
404
|
+
assert_equal 2, total_hits
|
|
405
|
+
#puts "first (id=#{contents_from_ferret.first[:id]}): #{contents_from_ferret.first[:score]}"
|
|
406
|
+
#puts "last (id=#{contents_from_ferret.last[:id]}): #{contents_from_ferret.last[:score]}"
|
|
407
|
+
assert_equal contents(:first).id, contents_from_ferret.first[:id].to_i
|
|
408
|
+
assert_equal @another_content.id, contents_from_ferret.last[:id].to_i
|
|
409
|
+
assert contents_from_ferret.first[:score] >= contents_from_ferret.last[:score]
|
|
410
|
+
|
|
411
|
+
# give description field higher boost:
|
|
412
|
+
total_hits, contents_from_ferret = Content.find_ids_with_ferret('title:title OR description:title^200')
|
|
413
|
+
assert_equal 2, contents_from_ferret.size
|
|
414
|
+
assert_equal 2, total_hits
|
|
415
|
+
#puts "first (id=#{contents_from_ferret.first[:id]}): #{contents_from_ferret.first[:score]}"
|
|
416
|
+
#puts "last (id=#{contents_from_ferret.last[:id]}): #{contents_from_ferret.last[:score]}"
|
|
417
|
+
assert_equal @another_content.id, contents_from_ferret.first[:id].to_i
|
|
418
|
+
assert_equal contents(:first).id, contents_from_ferret.last[:id].to_i
|
|
419
|
+
assert contents_from_ferret.first[:score] > contents_from_ferret.last[:score]
|
|
420
|
+
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def test_find_with_ferret_boost
|
|
424
|
+
# give description field higher boost:
|
|
425
|
+
contents_from_ferret = Content.find_with_ferret('title:title OR description:title^200')
|
|
426
|
+
assert_equal 2, contents_from_ferret.size
|
|
427
|
+
assert_equal @another_content.id, contents_from_ferret.first.id
|
|
428
|
+
assert_equal contents(:first).id, contents_from_ferret.last.id
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def test_default_and_queries
|
|
432
|
+
# multiple terms are ANDed by default...
|
|
433
|
+
contents_from_ferret = Content.find_with_ferret('monkey description')
|
|
434
|
+
assert contents_from_ferret.empty?
|
|
435
|
+
# ...unless you connect them by OR
|
|
436
|
+
contents_from_ferret = Content.find_with_ferret('monkey OR description')
|
|
437
|
+
assert_equal 1, contents_from_ferret.size
|
|
438
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
439
|
+
|
|
440
|
+
# multiple terms, each term has to occur in a document to be found,
|
|
441
|
+
# but they may occur in different fields
|
|
442
|
+
contents_from_ferret = Content.find_with_ferret('useless title')
|
|
443
|
+
assert_equal 1, contents_from_ferret.size
|
|
444
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
def test_find_with_ferret
|
|
448
|
+
|
|
449
|
+
contents_from_ferret = Content.find_with_ferret('lorem ipsum not here')
|
|
450
|
+
assert contents_from_ferret.empty?
|
|
451
|
+
|
|
452
|
+
contents_from_ferret = Content.find_with_ferret('title')
|
|
453
|
+
assert_equal 2, contents_from_ferret.size
|
|
454
|
+
# the title field has a higher boost value, so contents(:first) must be first in the list
|
|
455
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
456
|
+
assert_equal @another_content.id, contents_from_ferret.last.id
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
contents_from_ferret = Content.find_with_ferret('useless')
|
|
461
|
+
assert_equal 1, contents_from_ferret.size
|
|
462
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
463
|
+
|
|
464
|
+
# no monkeys here
|
|
465
|
+
contents_from_ferret = Content.find_with_ferret('monkey')
|
|
466
|
+
assert contents_from_ferret.empty?
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
# search for an exact string by enclosing it in "
|
|
471
|
+
contents_from_ferret = Content.find_with_ferret('"useless title"')
|
|
472
|
+
assert contents_from_ferret.empty?
|
|
473
|
+
contents_from_ferret = Content.find_with_ferret('"useless description"')
|
|
474
|
+
assert_equal 1, contents_from_ferret.size
|
|
475
|
+
assert_equal contents(:first).id, contents_from_ferret.first.id
|
|
476
|
+
|
|
477
|
+
# wildcard query
|
|
478
|
+
contents_from_ferret = Content.find_with_ferret('use*')
|
|
479
|
+
assert_equal 1, contents_from_ferret.size
|
|
480
|
+
|
|
481
|
+
# ferret-bug ? wildcard queries don't seem to get lowercased even when
|
|
482
|
+
# using StandardAnalyzer:
|
|
483
|
+
# contents_from_ferret = Content.find_with_ferret('Ti*')
|
|
484
|
+
# we should find both 'Title' and 'title'
|
|
485
|
+
# assert_equal 2, contents_from_ferret.size
|
|
486
|
+
# theory: :wild_lower parser option isn't used
|
|
487
|
+
|
|
488
|
+
contents_from_ferret = Content.find_with_ferret('ti*')
|
|
489
|
+
# this time we find both 'Title' and 'title'
|
|
490
|
+
assert_equal 2, contents_from_ferret.size
|
|
491
|
+
|
|
492
|
+
contents(:first).destroy
|
|
493
|
+
contents_from_ferret = Content.find_with_ferret('ti*')
|
|
494
|
+
# should find only one now
|
|
495
|
+
assert_equal 1, contents_from_ferret.size
|
|
496
|
+
assert_equal @another_content.id, contents_from_ferret.first.id
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
def test_find_with_ferret_options
|
|
500
|
+
# find options
|
|
501
|
+
contents_from_ferret = Content.find_with_ferret('title', {}, :conditions => ["id=?",contents(:first).id])
|
|
502
|
+
assert_equal 1, contents_from_ferret.size
|
|
503
|
+
assert_equal contents(:first), contents_from_ferret.first
|
|
504
|
+
|
|
505
|
+
# limit result set size to 1
|
|
506
|
+
contents_from_ferret = Content.find_with_ferret('title', :limit => 1)
|
|
507
|
+
assert_equal 1, contents_from_ferret.size
|
|
508
|
+
assert_equal contents(:first), contents_from_ferret.first
|
|
509
|
+
|
|
510
|
+
# limit result set size to 1, starting with the second result
|
|
511
|
+
contents_from_ferret = Content.find_with_ferret('title', :limit => 1, :offset => 1)
|
|
512
|
+
assert_equal 1, contents_from_ferret.size
|
|
513
|
+
assert_equal @another_content.id, contents_from_ferret.first.id
|
|
514
|
+
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def test_pagination
|
|
518
|
+
more_contents
|
|
519
|
+
|
|
520
|
+
r = Content.find_with_ferret 'title', :per_page => 10, :sort => 'title'
|
|
521
|
+
assert_equal 30, r.total_hits
|
|
522
|
+
assert_equal 10, r.size
|
|
523
|
+
assert_equal "0", r.first.description
|
|
524
|
+
assert_equal "9", r.last.description
|
|
525
|
+
assert_equal 1, r.current_page
|
|
526
|
+
assert_equal 3, r.page_count
|
|
527
|
+
|
|
528
|
+
r = Content.find_with_ferret 'title', :page => '2', :per_page => 10, :sort => 'title'
|
|
529
|
+
assert_equal 30, r.total_hits
|
|
530
|
+
assert_equal 10, r.size
|
|
531
|
+
assert_equal "10", r.first.description
|
|
532
|
+
assert_equal "19", r.last.description
|
|
533
|
+
assert_equal 2, r.current_page
|
|
534
|
+
assert_equal 3, r.page_count
|
|
535
|
+
|
|
536
|
+
r = Content.find_with_ferret 'title', :page => 4, :per_page => 10, :sort => 'title'
|
|
537
|
+
assert_equal 30, r.total_hits
|
|
538
|
+
assert_equal 0, r.size
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
def test_limits_and_offsets
|
|
542
|
+
more_contents
|
|
543
|
+
r = Content.find_with_ferret 'title'
|
|
544
|
+
assert_equal 30, r.total_hits
|
|
545
|
+
assert_equal 10, r.size
|
|
546
|
+
|
|
547
|
+
r = Content.find_with_ferret 'title', :limit => :all
|
|
548
|
+
assert_equal 30, r.total_hits
|
|
549
|
+
assert_equal 30, r.size
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def test_limits_and_offsets_with_ar_conditions
|
|
553
|
+
more_contents
|
|
554
|
+
|
|
555
|
+
r = Content.find_with_ferret 'title', { :limit => 10, :offset => 0 },
|
|
556
|
+
{ :conditions => "description != '0'", :order => 'title ASC' }
|
|
557
|
+
assert_equal 29, r.total_hits
|
|
558
|
+
assert_equal 10, r.size
|
|
559
|
+
assert_equal "1", r.first.description
|
|
560
|
+
assert_equal "10", r.last.description
|
|
561
|
+
|
|
562
|
+
r = Content.find_with_ferret 'title', { :limit => 10, :offset => 10 },
|
|
563
|
+
{ :conditions => "description != '0'", :order => 'title ASC' }
|
|
564
|
+
assert_equal 29, r.total_hits
|
|
565
|
+
assert_equal 10, r.size
|
|
566
|
+
assert_equal "11", r.first.description
|
|
567
|
+
assert_equal "20", r.last.description
|
|
568
|
+
|
|
569
|
+
r = Content.find_with_ferret 'title', { },
|
|
570
|
+
{ :conditions => "description != '0'", :order => 'title ASC',
|
|
571
|
+
:limit => 10, :offset => 0 }
|
|
572
|
+
assert_equal 29, r.total_hits
|
|
573
|
+
assert_equal 10, r.size
|
|
574
|
+
assert_equal "1", r.first.description
|
|
575
|
+
assert_equal "10", r.last.description
|
|
576
|
+
|
|
577
|
+
r = Content.find_with_ferret 'title', { },
|
|
578
|
+
{ :conditions => "description != '0'", :order => 'title ASC',
|
|
579
|
+
:limit => 10, :offset => 10 }
|
|
580
|
+
assert_equal 29, r.total_hits
|
|
581
|
+
assert_equal 10, r.size
|
|
582
|
+
assert_equal "11", r.first.description
|
|
583
|
+
assert_equal "20", r.last.description
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
def test_pagination_with_ar_conditions
|
|
587
|
+
more_contents
|
|
588
|
+
|
|
589
|
+
r = Content.find_with_ferret 'title', { :page => 1, :per_page => 10 },
|
|
590
|
+
{ :conditions => "description != '0'", :order => 'title ASC' }
|
|
591
|
+
assert_equal 29, r.total_hits
|
|
592
|
+
assert_equal 10, r.size
|
|
593
|
+
assert_equal "1", r.first.description
|
|
594
|
+
assert_equal "10", r.last.description
|
|
595
|
+
assert_equal 1, r.current_page
|
|
596
|
+
assert_equal 3, r.page_count
|
|
597
|
+
|
|
598
|
+
r = Content.find_with_ferret 'title', { :page => 3, :per_page => 10 },
|
|
599
|
+
{ :conditions => "description != '0'", :order => 'title ASC' }
|
|
600
|
+
assert_equal 9, r.size
|
|
601
|
+
assert_equal 29, r.total_hits
|
|
602
|
+
assert_equal "21", r.first.description
|
|
603
|
+
assert_equal "29", r.last.description
|
|
604
|
+
assert_equal 3, r.current_page
|
|
605
|
+
assert_equal 3, r.page_count
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
def test_pagination_with_ar_conditions_and_ferret_sort
|
|
609
|
+
more_contents
|
|
610
|
+
|
|
611
|
+
# r = Content.find_with_ferret 'title', { :page => 1, :per_page => 10,
|
|
612
|
+
# :sort => Ferret::Search::SortField.new(:id,
|
|
613
|
+
# :type => :integer,
|
|
614
|
+
# :reverse => true ) },
|
|
615
|
+
# { :conditions => "description != '0'" }
|
|
616
|
+
r = ActsAsFerret::find 'title', Content, { :page => 1, :per_page => 10,
|
|
617
|
+
:sort => Ferret::Search::SortField.new(:id,
|
|
618
|
+
:type => :integer,
|
|
619
|
+
:reverse => true ) },
|
|
620
|
+
{ :conditions => "description != '29'" }
|
|
621
|
+
assert_equal 29, r.total_hits
|
|
622
|
+
assert_equal 10, r.size
|
|
623
|
+
assert_equal "28", r.first.description
|
|
624
|
+
assert_equal "19", r.last.description
|
|
625
|
+
assert_equal 1, r.current_page
|
|
626
|
+
assert_equal 3, r.page_count
|
|
627
|
+
|
|
628
|
+
r = Content.find_with_ferret 'title', { :page => 3, :per_page => 10 },
|
|
629
|
+
{ :conditions => "description != '0'", :order => 'title ASC' }
|
|
630
|
+
assert_equal 9, r.size
|
|
631
|
+
assert_equal 29, r.total_hits
|
|
632
|
+
assert_equal "21", r.first.description
|
|
633
|
+
assert_equal "29", r.last.description
|
|
634
|
+
assert_equal 3, r.current_page
|
|
635
|
+
assert_equal 3, r.page_count
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
def test_pagination_with_more_conditions
|
|
639
|
+
more_contents
|
|
640
|
+
|
|
641
|
+
r = Content.find_with_ferret 'title -description:0', { :page => 1, :per_page => 10 },
|
|
642
|
+
{ :conditions => "contents.description != '9'", :order => 'title ASC' }
|
|
643
|
+
assert_equal 28, r.total_hits
|
|
644
|
+
assert_equal 10, r.size
|
|
645
|
+
assert_equal "1", r.first.description
|
|
646
|
+
assert_equal "11", r.last.description
|
|
647
|
+
assert_equal 1, r.current_page
|
|
648
|
+
assert_equal 3, r.page_count
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
def test_reconnect_in_drb_mode
|
|
652
|
+
if ENV['AAF_REMOTE'] && Content.connection.is_a?(ActiveRecord::ConnectionAdapters::MysqlAdapter)
|
|
653
|
+
puts "have DRb and MySQL - doing db reconnect test"
|
|
654
|
+
Content.aaf_index.send(:db_disconnect!)
|
|
655
|
+
c = Content.create! :title => 'another one', :description => 'description'
|
|
656
|
+
assert_equal c, Content.find_with_ferret('another').first
|
|
657
|
+
else
|
|
658
|
+
assert true
|
|
659
|
+
end
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
def test_per_field_boost
|
|
663
|
+
Content.destroy_all
|
|
664
|
+
Content.create! :title => 'the title'
|
|
665
|
+
boosted = Content.new :title => 'the title'
|
|
666
|
+
boosted.title_boost = 100
|
|
667
|
+
boosted.save!
|
|
668
|
+
Content.create! :title => 'the title'
|
|
669
|
+
results = Content.find_with_ferret 'title:title'
|
|
670
|
+
assert_equal 3, results.size
|
|
671
|
+
assert_equal boosted.id, results.first.id
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
def test_per_document_boost
|
|
675
|
+
Content.destroy_all
|
|
676
|
+
Content.create! :title => 'the title'
|
|
677
|
+
boosted = Content.new :title => 'the title'
|
|
678
|
+
boosted.record_boost = 10
|
|
679
|
+
boosted.save!
|
|
680
|
+
Content.create! :title => 'the title'
|
|
681
|
+
results = Content.find_with_ferret 'title'
|
|
682
|
+
assert_equal 3, results.size
|
|
683
|
+
assert_equal boosted.id, results.first.id
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
protected
|
|
688
|
+
|
|
689
|
+
def more_contents(with_comments = false)
|
|
690
|
+
Comment.destroy_all if with_comments
|
|
691
|
+
Content.destroy_all
|
|
692
|
+
SpecialContent.destroy_all
|
|
693
|
+
30.times do |i|
|
|
694
|
+
c = Content.create! :title => sprintf("title of Content %02d", i), :description => "#{i}"
|
|
695
|
+
c.comments.create! :content => sprintf("Comment for content %02d", i) if with_comments
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
def remove_index(clazz)
|
|
700
|
+
clazz.aaf_index.close # avoid io error when deleting the open index
|
|
701
|
+
FileUtils.rm_rf clazz.aaf_configuration[:index_dir]
|
|
702
|
+
assert !File.exists?("#{clazz.aaf_configuration[:index_dir]}/segments")
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
end
|