pg_search 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -0
- data/README.rdoc +2 -2
- data/lib/pg_search.rb +2 -0
- data/lib/pg_search/configuration.rb +8 -0
- data/lib/pg_search/configuration/association.rb +6 -1
- data/lib/pg_search/features/tsearch.rb +18 -12
- data/lib/pg_search/normalizer.rb +10 -1
- data/lib/pg_search/version.rb +1 -1
- data/spec/pg_search_spec.rb +19 -11
- data/spec/spec_helper.rb +3 -1
- metadata +63 -41
data/CHANGELOG
CHANGED
data/README.rdoc
CHANGED
@@ -105,7 +105,7 @@ To remove all of the documents for a given class, you can simply delete all of t
|
|
105
105
|
|
106
106
|
Run this Rake task to regenerate all of the documents for a given class.
|
107
107
|
|
108
|
-
$ rake pg_search:multisearch:rebuild
|
108
|
+
$ rake pg_search:multisearch:rebuild MODEL=BlogPost
|
109
109
|
|
110
110
|
Currently this is only supported for :against methods that directly map to Active Record attributes. Until that is fixed, you could also manually rebuild all of the documents.
|
111
111
|
|
@@ -414,7 +414,7 @@ Trigram support is currently available as part of the {pg_trgm contrib package}[
|
|
414
414
|
|
415
415
|
Website.kinda_spelled_like("Yahoo!") # => [yahooo, yohoo]
|
416
416
|
|
417
|
-
=== Ignoring accent marks
|
417
|
+
=== Ignoring accent marks (PostgreSQL 9.0 and above only)
|
418
418
|
|
419
419
|
Most of the time you will want to ignore accent marks when searching. This makes it possible to find words like "piñata" when searching with the query "pinata". If you set a pg_search_scope to ignore accents, it will ignore accents in both the searchable text and the query terms.
|
420
420
|
|
data/lib/pg_search.rb
CHANGED
@@ -19,7 +19,12 @@ module PgSearch
|
|
19
19
|
|
20
20
|
def join(primary_key)
|
21
21
|
selects = columns.map do |column|
|
22
|
-
|
22
|
+
case @model.connection.send(:postgresql_version)
|
23
|
+
when 0..90000
|
24
|
+
"array_to_string(array_agg(#{column.full_name}), ' ') AS #{column.alias}"
|
25
|
+
else
|
26
|
+
"string_agg(#{column.full_name}, ' ') AS #{column.alias}"
|
27
|
+
end
|
23
28
|
end.join(", ")
|
24
29
|
relation = @model.joins(@name).select("#{primary_key} AS id, #{selects}").group(primary_key)
|
25
30
|
"LEFT OUTER JOIN (#{relation.to_sql}) #{subselect_alias} ON #{subselect_alias}.id = #{primary_key}"
|
@@ -31,22 +31,28 @@ module PgSearch
|
|
31
31
|
@columns.map { |column| column.to_sql }.join(" || ' ' || ")
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
return "''" if @query.blank?
|
34
|
+
DISALLOWED_TSQUERY_CHARACTERS = /['?\-\\:]/
|
36
35
|
|
37
|
-
|
38
|
-
|
36
|
+
def tsquery_for_term(term)
|
37
|
+
sanitized_term = term.gsub(DISALLOWED_TSQUERY_CHARACTERS, " ")
|
39
38
|
|
40
|
-
|
39
|
+
term_sql = @normalizer.add_normalization(connection.quote(sanitized_term))
|
41
40
|
|
42
|
-
|
43
|
-
|
41
|
+
# After this, the SQL expression evaluates to a string containing the term surrounded by single-quotes.
|
42
|
+
# If :prefix is true, then the term will also have :* appended to the end.
|
43
|
+
tsquery_sql = [
|
44
|
+
connection.quote("' "),
|
45
|
+
term_sql,
|
46
|
+
connection.quote(" '"),
|
47
|
+
(connection.quote(':*') if @options[:prefix])
|
48
|
+
].compact.join(" || ")
|
44
49
|
|
45
|
-
|
46
|
-
|
50
|
+
"to_tsquery(:dictionary, #{tsquery_sql})"
|
51
|
+
end
|
47
52
|
|
48
|
-
|
49
|
-
|
53
|
+
def tsquery
|
54
|
+
return "''" if @query.blank?
|
55
|
+
@query.split(" ").compact.map { |term| tsquery_for_term(term) }.join(@options[:any_word] ? ' || ' : ' && ')
|
50
56
|
end
|
51
57
|
|
52
58
|
def tsdocument
|
@@ -55,7 +61,7 @@ module PgSearch
|
|
55
61
|
search_column.weight.nil? ? tsvector : "setweight(#{tsvector}, #{connection.quote(search_column.weight)})"
|
56
62
|
end.join(" || ")
|
57
63
|
end
|
58
|
-
|
64
|
+
|
59
65
|
# From http://www.postgresql.org/docs/8.3/static/textsearch-controls.html
|
60
66
|
# 0 (the default) ignores the document length
|
61
67
|
# 1 divides the rank by 1 + the logarithm of the document length
|
data/lib/pg_search/normalizer.rb
CHANGED
@@ -6,7 +6,16 @@ module PgSearch
|
|
6
6
|
|
7
7
|
def add_normalization(original_sql)
|
8
8
|
normalized_sql = original_sql
|
9
|
-
|
9
|
+
if @config.ignore.include?(:accents)
|
10
|
+
if @config.postgresql_version < 90000
|
11
|
+
raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE)
|
12
|
+
Sorry, {:ignoring => :accents} only works in PostgreSQL 9.0 and above.
|
13
|
+
#{@config.inspect}
|
14
|
+
MESSAGE
|
15
|
+
else
|
16
|
+
normalized_sql = "unaccent(#{normalized_sql})"
|
17
|
+
end
|
18
|
+
end
|
10
19
|
normalized_sql
|
11
20
|
end
|
12
21
|
end
|
data/lib/pg_search/version.rb
CHANGED
data/spec/pg_search_spec.rb
CHANGED
@@ -369,14 +369,14 @@ describe "an ActiveRecord model which includes PgSearch" do
|
|
369
369
|
results.should =~ included
|
370
370
|
end
|
371
371
|
end
|
372
|
-
|
372
|
+
|
373
373
|
describe "ranking" do
|
374
374
|
before do
|
375
375
|
["Strip Down", "Down", "Down and Out", "Won't Let You Down"].each do |name|
|
376
376
|
ModelWithPgSearch.create! :content => name
|
377
377
|
end
|
378
378
|
end
|
379
|
-
|
379
|
+
|
380
380
|
context "with a normalization specified" do
|
381
381
|
before do
|
382
382
|
ModelWithPgSearch.class_eval do
|
@@ -389,12 +389,12 @@ describe "an ActiveRecord model which includes PgSearch" do
|
|
389
389
|
end
|
390
390
|
it "ranks the results for documents with less text higher" do
|
391
391
|
results = ModelWithPgSearch.search_content_with_normalization("down")
|
392
|
-
|
392
|
+
|
393
393
|
results.map(&:content).should == ["Down", "Strip Down", "Down and Out", "Won't Let You Down"]
|
394
394
|
results.first.rank.should be > results.last.rank
|
395
395
|
end
|
396
396
|
end
|
397
|
-
|
397
|
+
|
398
398
|
context "with no normalization" do
|
399
399
|
before do
|
400
400
|
ModelWithPgSearch.class_eval do
|
@@ -405,7 +405,7 @@ describe "an ActiveRecord model which includes PgSearch" do
|
|
405
405
|
end
|
406
406
|
it "ranks the results equally" do
|
407
407
|
results = ModelWithPgSearch.search_content_without_normalization("down")
|
408
|
-
|
408
|
+
|
409
409
|
results.map(&:content).should == ["Strip Down", "Down", "Down and Out", "Won't Let You Down"]
|
410
410
|
results.first.rank.should == results.last.rank
|
411
411
|
end
|
@@ -599,14 +599,22 @@ describe "an ActiveRecord model which includes PgSearch" do
|
|
599
599
|
end
|
600
600
|
end
|
601
601
|
|
602
|
-
|
603
|
-
|
604
|
-
|
602
|
+
if ActiveRecord::Base.connection.send(:postgresql_version) < 90000
|
603
|
+
it "is unsupported in PostgreSQL 8.x" do
|
604
|
+
lambda do
|
605
|
+
ModelWithPgSearch.search_title_without_accents("abcd\303\251f")
|
606
|
+
end.should raise_exception(PgSearch::NotSupportedForPostgresqlVersion)
|
607
|
+
end
|
608
|
+
else
|
609
|
+
it "returns rows that match the query but not its accents" do
|
610
|
+
# \303\241 is a with acute accent
|
611
|
+
# \303\251 is e with acute accent
|
605
612
|
|
606
|
-
|
613
|
+
included = ModelWithPgSearch.create!(:title => "\303\241bcdef")
|
607
614
|
|
608
|
-
|
609
|
-
|
615
|
+
results = ModelWithPgSearch.search_title_without_accents("abcd\303\251f")
|
616
|
+
results.should == [included]
|
617
|
+
end
|
610
618
|
end
|
611
619
|
end
|
612
620
|
|
data/spec/spec_helper.rb
CHANGED
@@ -35,7 +35,9 @@ rescue => e
|
|
35
35
|
end
|
36
36
|
|
37
37
|
install_contrib_module_if_missing("pg_trgm", "SELECT 'abcdef' % 'cdef'", "t")
|
38
|
-
|
38
|
+
unless connection.send(:postgresql_version) < 90000
|
39
|
+
install_contrib_module_if_missing("unaccent", "SELECT unaccent('foo')", "foo")
|
40
|
+
end
|
39
41
|
install_contrib_module_if_missing("fuzzystrmatch", "SELECT dmetaphone('foo')", "f")
|
40
42
|
|
41
43
|
ActiveRecord::Base.connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'dmetaphone.sql')))
|
metadata
CHANGED
@@ -1,46 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_search
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
- 2
|
10
|
+
version: 0.3.2
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Case Commons, LLC
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2011-10-18 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: activerecord
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 5
|
29
|
+
segments:
|
30
|
+
- 3
|
31
|
+
version: "3"
|
22
32
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
26
35
|
name: activesupport
|
27
|
-
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
38
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 5
|
43
|
+
segments:
|
44
|
+
- 3
|
45
|
+
version: "3"
|
33
46
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
full text search
|
38
|
-
email:
|
47
|
+
version_requirements: *id002
|
48
|
+
description: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search
|
49
|
+
email:
|
39
50
|
- casecommons-dev@googlegroups.com
|
40
51
|
executables: []
|
52
|
+
|
41
53
|
extensions: []
|
54
|
+
|
42
55
|
extra_rdoc_files: []
|
43
|
-
|
56
|
+
|
57
|
+
files:
|
44
58
|
- .autotest
|
45
59
|
- .gitignore
|
46
60
|
- .rspec
|
@@ -80,30 +94,38 @@ files:
|
|
80
94
|
- sql/uninstall_dmetaphone.sql
|
81
95
|
homepage: https://github.com/Casecommons/pg_search
|
82
96
|
licenses: []
|
97
|
+
|
83
98
|
post_install_message:
|
84
99
|
rdoc_options: []
|
85
|
-
|
100
|
+
|
101
|
+
require_paths:
|
86
102
|
- lib
|
87
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
104
|
none: false
|
89
|
-
requirements:
|
90
|
-
- -
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
|
93
|
-
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 3
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
version: "0"
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
113
|
none: false
|
95
|
-
requirements:
|
96
|
-
- -
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 3
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
99
121
|
requirements: []
|
122
|
+
|
100
123
|
rubyforge_project:
|
101
|
-
rubygems_version: 1.8.
|
124
|
+
rubygems_version: 1.8.4
|
102
125
|
signing_key:
|
103
126
|
specification_version: 3
|
104
|
-
summary: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's
|
105
|
-
|
106
|
-
test_files:
|
127
|
+
summary: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search
|
128
|
+
test_files:
|
107
129
|
- spec/associations_spec.rb
|
108
130
|
- spec/pg_search/document_spec.rb
|
109
131
|
- spec/pg_search/multisearch_spec.rb
|