Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 593 lines (406 sloc) 25.852 kb
50b955f @nertzy Add the beginnings of a README
nertzy authored
1 = pg_search
2
3 * http://github.com/casecommons/pg_search/
4
4eec667 Add Code Climate badge to README
Grant Hutchins & Nishit Shah authored
5 {<img src="https://secure.travis-ci.org/Casecommons/pg_search.png?branch=master" alt="Build Status" />}[http://travis-ci.org/Casecommons/pg_search] {<img src="https://gemnasium.com/Casecommons/pg_search.png" alt="Dependency Status" />}[https://gemnasium.com/Casecommons/pg_search] {<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/Casecommons/pg_search]
598aea0 @nertzy Add images for Travis CI and Gemnasium
nertzy authored
6
30daa11 Remove extra colons from README
Grant Hutchins & Rachel Heaton authored
7 == DESCRIPTION
50b955f @nertzy Add the beginnings of a README
nertzy authored
8
9 PgSearch builds named scopes that take advantage of PostgreSQL's full text search
10
92bd18e @nertzy Add link to blog post
nertzy authored
11 Read the blog post introducing PgSearch at http://bit.ly/pg_search
12
30daa11 Remove extra colons from README
Grant Hutchins & Rachel Heaton authored
13 == INSTALL
50b955f @nertzy Add the beginnings of a README
nertzy authored
14
15 gem install pg_search
16
17 === Rails 3
18
19 In Gemfile
20
21 gem 'pg_search'
22
553fee8 @nertzy Add information about the 0.2 series
nertzy authored
23 === Rails 2
24
25 The newest versions of PgSearch no longer support Rails 2. However, the 0.2 series still works. It's not actively maintained, but submissions are welcome for backports and bugfixes.
26
27 The 0.2 branch lives at https://github.com/Casecommons/pg_search/tree/0.2-stable
28
13cb6f0 Use a Railtie to load rake tasks
Grant Hutchins & Peter Jaros authored
29 === Other ActiveRecord-based projects
30
ed97020 @nertzy Rails projects don't need to include tasks.rb
nertzy authored
31 In addition to installing and requiring the gem, you may want to include the PgSearch rake tasks in your Rakefile. This isn't necessary for Rails projects, which gain the Rake tasks via a Railtie.
13cb6f0 Use a Railtie to load rake tasks
Grant Hutchins & Peter Jaros authored
32
33 load "pg_search/tasks.rb"
34
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
35 == USAGE
36
37 To add PgSearch to an ActiveRecord model, simply include the PgSearch module.
38
39 class Shape < ActiveRecord::Base
40 include PgSearch
41 end
42
b72d530 @nertzy Documentation for multi-search
nertzy authored
43 === Multi-search vs. search scopes
44
45 pg_search supports two different techniques for searching, multi-search and search scopes.
46
47 The first technique is multi-search, in which records of many different Active Record classes can be mixed together into one global search index across your entire application. Most sites that want to support a generic search page will want to use this feature.
48
49 The other technique is search scopes, which allow you to do more advanced searching against only one Active Record class. This is more useful for building things like autocompleters or filtering a list of items in a faceted search.
50
51 === Multi-search
52
53 ==== Setup
54
55 Before using multi-search, you must generate and run a migration to create the pg_search_documents database table.
56
7cdbced @nertzy Convert rake tasks into generators
nertzy authored
57 $ rails g pg_search:migration:multisearch
b72d530 @nertzy Documentation for multi-search
nertzy authored
58 $ rake db:migrate
59
60 ==== multisearchable
61
62 To add a model to the global search index for your application, call multisearchable in its class definition.
63
64 class EpicPoem < ActiveRecord::Base
65 include PgSearch
66 multisearchable :against => [:title, :author]
67 end
68
69 class Flower < ActiveRecord::Base
70 include PgSearch
71 multisearchable :against => :color
72 end
73
74 Whenever a record is created, updated, or destroyed, an Active Record callback will fire, leading to the creation of a corresponding PgSearch::Document record in the pg_search_documents table. The :against option can be one or several methods which will be called on the record to generate its search text.
75
10e4a1e @nertzy Add documentation for multisearchable conditional
nertzy authored
76 You can also pass a Proc or method name to call to determine whether or not a particular record should be included.
77
78 class Convertible < ActiveRecord::Base
79 include PgSearch
80 multisearchable :against => [:make, :model],
81 :if => :available_in_red?
82 end
83
84 class Jalopy < ActiveRecord::Base
85 include PgSearch
86 multisearchable :against => [:make, :model],
87 :if => lambda { |record| record.model_year > 1970 }
88 end
89
d948910 @nertzy Add warning about incorrect usage of :if/:unless in .multisearchable
nertzy authored
90 Note that the Proc or method name is called in an after_save hook. This means that you should be careful when using Time or other objects. In the following example, if the record was last saved before the published_at timestamp, it won't get listed in global search at all until it is touched again after the timestamp.
91
92 class AntipatternExample
93 include PgSearch
94 multisearchable :against => [:contents],
95 :if => :published?
96
97 def published?
98 published_at < Time.now
99 end
100 end
101
102 problematic_record = AntipatternExample.create!(
103 :contents => "Using :if with a timestamp",
104 :published_at => 10.minutes.from_now
105 )
106
107 problematic_record.published? # => false
108 PgSearch.multisearch("timestamp") # => No results
109
110 sleep 20.minutes
111
112 problematic_record.published? # => true
113 PgSearch.multisearch("timestamp") # => No results
114
115 problematic_record.save!
116
117 problematic_record.published? # => true
118 PgSearch.multisearch("timestamp") # => Includes problematic_record
119
b72d530 @nertzy Documentation for multi-search
nertzy authored
120 ==== Multi-search associations
121
122 Two associations are built automatically. On the original record, there is a has_one :pg_search_document association pointing to the PgSearch::Document record, and on the PgSearch::Document record there is a belongs_to :searchable polymorphic association pointing back to the original record.
123
124 odyssey = EpicPoem.create!(:title => "Odyssey", :author => "Homer")
125 search_document = odyssey.pg_search_document #=> PgSearch::Document instance
126 search_document.searchable #=> #<EpicPoem id: 1, title: "Odyssey", author: "Homer">
127
128 ==== Searching in the global search index
129
d6ce97c PgSearch.multisearch now has options
Grant Hutchins & Joe Moore authored
130 To fetch the PgSearch::Document entries for all of the records that match a given query, use PgSearch.multisearch.
b72d530 @nertzy Documentation for multi-search
nertzy authored
131
132 odyssey = EpicPoem.create!(:title => "Odyssey", :author => "Homer")
133 rose = Flower.create!(:color => "Red")
134 PgSearch.multisearch("Homer") #=> [#<PgSearch::Document searchable: odyssey>]
135 PgSearch.multisearch("Red") #=> [#<PgSearch::Document searchable: rose>]
136
137 ==== Chaining method calls onto the results
138
139 PgSearch.multisearch returns an ActiveRecord::Relation, just like scopes do, so you can chain scope calls to the end. This works with gems like Kaminari that add scope methods. Just like with regular scopes, the database will only receive SQL requests when necessary.
140
141 PgSearch.multisearch("Bertha").limit(10)
142 PgSearch.multisearch("Juggler").where(:searchable_type => "Occupation")
143 PgSearch.multisearch("Alamo").page(3).per_page(30)
3b6dee0 @asanghi fixed minor typo
asanghi authored
144 PgSearch.multisearch("Diagonal").find_each do |document|
b72d530 @nertzy Documentation for multi-search
nertzy authored
145 puts document.searchable.updated_at
146 end
147
d6ce97c PgSearch.multisearch now has options
Grant Hutchins & Joe Moore authored
148 ==== Configuring multi-search
149
84da89d @mrhaddad Update README
mrhaddad authored
150 PgSearch.multisearch can be configured using the same options as `pg_search_scope` (explained in more detail below). Just set the PgSearch.multisearch_options in an initializer:
d6ce97c PgSearch.multisearch now has options
Grant Hutchins & Joe Moore authored
151
84da89d @mrhaddad Update README
mrhaddad authored
152 PgSearch.multisearch_options = {
d6ce97c PgSearch.multisearch now has options
Grant Hutchins & Joe Moore authored
153 :using => [:tsearch, :trigram],
154 :ignoring => :accents
155 }
156
b72d530 @nertzy Documentation for multi-search
nertzy authored
157 ==== Rebuilding search documents for a given class
158
159 If you change the :against option on a class, add multisearchable to a class that already has records in the database, or remove multisearchable from a class in order to remove it from the index, you will find that the pg_search_documents table could become out-of-sync with the actual records in your other tables.
160
161 The index can also become out-of-sync if you ever modify records in a way that does not trigger Active Record callbacks. For instance, the #update_attribute instance method and the .update_all class method both skip callbacks and directly modify the database.
162
163 To remove all of the documents for a given class, you can simply delete all of the PgSearch::Document records.
164
165 PgSearch::Document.delete_all(:searchable_type => "Animal")
166
167 Run this Rake task to regenerate all of the documents for a given class.
168
27d7afa @nertzy Use rake task arguments for multisearch rebuild
nertzy authored
169 $ rake pg_search:multisearch:rebuild[BlogPost]
b72d530 @nertzy Documentation for multi-search
nertzy authored
170
171 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.
172
173 PgSearch::Document.delete_all(:searchable_type => "Ingredient")
174 Ingredient.find_each { |record| record.update_pg_search_document }
175
4ab4f37 @nertzy Add ability to override multisearch rebuild SQL
nertzy authored
176
177 You can also provide a custom implementation for rebuilding the documents by adding a class method called `rebuild_pg_search_documents` to your model.
178
179 class Movie < ActiveRecord::Base
180 belongs_to :director
181
182 def director_name
183 director.name
184 end
185
186 multisearchable against: [:name, :director_name]
187
188 # Naive approach
189 def self.rebuild_pg_search_documents
190 find_each { |record| record.update_pg_search_document }
191 end
192
193 # More sophisticated approach
194 def self.rebuild_pg_search_documents
195 connection.execute <<-SQL
196 INSERT INTO pg_search_documents (searchable_type, searchable_id, content, created_at, updated_at)
197 SELECT 'Movie' AS searchable_type,
198 movies.id AS searchable_id,
199 (movies.name || ' ' || directors.name) AS content,
200 now() AS created_at,
201 now() AS updated_at
202 FROM movies
203 LEFT JOIN directors
204 ON directors.id = movies.director_id
205 SQL
206 end
207 end
208
b72d530 @nertzy Documentation for multi-search
nertzy authored
209 ==== Disabling multi-search indexing temporarily
210
211 If you have a large bulk operation to perform, such as importing a lot of records from an external source, you might want to speed things up by turning off indexing temporarily. You could then use one of the techniques above to rebuild the search documents off-line.
212
213 PgSearch.disable_multisearch do
214 Movie.import_from_xml_file(File.open("movies.xml"))
215 end
216
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
217 === pg_search_scope
218
219 You can use pg_search_scope to build a search scope. The first parameter is a scope name, and the second parameter is an options hash. The only required option is :against, which tells pg_search_scope which column or columns to search against.
220
221 ==== Searching against one column
222
223 To search against a column, pass a symbol as the :against option.
224
225 class BlogPost < ActiveRecord::Base
226 include PgSearch
227 pg_search_scope :search_by_title, :against => :title
228 end
229
230 We now have an ActiveRecord scope named search_by_title on our BlogPost model. It takes one parameter, a search query string.
231
232 BlogPost.create!(:title => "Recent Developments in the World of Pastrami")
233 BlogPost.create!(:title => "Prosciutto and You: A Retrospective")
234 BlogPost.search_by_title("pastrami") # => [#<BlogPost id: 2, title: "Recent Developments in the World of Pastrami">]
235
236 ==== Searching against multiple columns
237
238 Just pass an Array if you'd like to search more than one column.
239
240 class Person < ActiveRecord::Base
241 include PgSearch
242 pg_search_scope :search_by_full_name, :against => [:first_name, :last_name]
243 end
244
245 Now our search query can match either or both of the columns.
246
247 person_1 = Person.create!(:first_name => "Grant", :last_name => "Hill")
248 person_2 = Person.create!(:first_name => "Hugh", :last_name => "Grant")
249
250 Person.search_by_full_name("Grant") # => [person_1, person_2]
251 Person.search_by_full_name("Grant Hill") # => [person_1]
252
3fae8e9 Document dynamic search scopes
Grant Hutchins & Rachel Heaton authored
253 ==== Dynamic search scopes
254
255 Just like with Active Record named scopes, you can pass in a Proc object that returns a hash of options. For instance, the following scope takes a parameter that dynamically chooses which column to search against.
256
257 Important: The returned hash must include a :query key. Its value does not necessary have to be dynamic. You could choose to hard-code it to a specific value if you wanted.
258
259 class Person < ActiveRecord::Base
260 include PgSearch
261 pg_search_scope :search_by_name, lambda do |name_part, query|
262 raise ArgumentError unless [:first, :last].include?(name_part)
263 {
264 :against => name_part,
265 :query => query
266 }
267 end
268 end
269
270 person_1 = Person.create!(:first_name => "Grant", :last_name => "Hill")
271 person_2 = Person.create!(:first_name => "Hugh", :last_name => "Grant")
272
273 Person.search_by_name :first, "Grant" # => [person_1]
274 Person.search_by_name :last, "Grant" # => [person_2]
275
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
276 ==== Searching through associations
277
5ff3fa3 @nertzy Backport array_agg() to PostgreSQL 8.3 and earlier
nertzy authored
278 It is possible to search columns on associated models. Note that if you do this, it will be impossible to speed up searches with database indexes. However, it is supported as a quick way to try out cross-model searching.
279
7cdbced @nertzy Convert rake tasks into generators
nertzy authored
280 In PostgreSQL 8.3 and earlier, you must install a utility function into your database. To generate and run a migration for this, run:
5ff3fa3 @nertzy Backport array_agg() to PostgreSQL 8.3 and earlier
nertzy authored
281
7cdbced @nertzy Convert rake tasks into generators
nertzy authored
282 $ rails g pg_search:migration:associated_against
283 $ rake db:migrate
5ff3fa3 @nertzy Backport array_agg() to PostgreSQL 8.3 and earlier
nertzy authored
284
285 This migration is safe to run against newer versions of PostgreSQL as well. It will essentially do nothing.
286
287 You can pass a Hash into the :associated_against option to set up searching through associations. The keys are the names of the associations and the value works just like an :against option for the other model. Right now, searching deeper than one association away is not supported. You can work around this by setting up a series of :through associations to point all the way through.
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
288
289 class Cracker < ActiveRecord::Base
7aaf61e Fix a typo in README
Grant Hutchins & Rachel Heaton authored
290 has_many :cheeses
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
291 end
292
293 class Cheese < ActiveRecord::Base
294 end
295
296 class Salami < ActiveRecord::Base
297 include PgSearch
3fae8e9 Document dynamic search scopes
Grant Hutchins & Rachel Heaton authored
298
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
299 belongs_to :cracker
300 has_many :cheeses, :through => :cracker
3fae8e9 Document dynamic search scopes
Grant Hutchins & Rachel Heaton authored
301
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
302 pg_search_scope :tasty_search, :associated_against => {
303 :cheeses => [:kind, :brand],
304 :cracker => :kind
305 }
306 end
307
308 salami_1 = Salami.create!
309 salami_2 = Salami.create!
310 salami_3 = Salami.create!
311
312 limburger = Cheese.create!(:kind => "Limburger")
313 brie = Cheese.create!(:kind => "Brie")
314 pepper_jack = Cheese.create!(:kind => "Pepper Jack")
315
316 Cracker.create!(:kind => "Black Pepper", :cheeses => [brie], :salami => salami_1)
317 Cracker.create!(:kind => "Ritz", :cheeses => [limburger, pepper_jack], :salami => salami_2)
318 Cracker.create!(:kind => "Graham", :cheeses => [limburger], :salami => salami_3)
3fae8e9 Document dynamic search scopes
Grant Hutchins & Rachel Heaton authored
319
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
320 Salami.tasty_search("pepper") # => [salami_1, salami_2]
321
322 === Searching using different search features
323
f872548 @nertzy Update README to reflect change from :features to :using
nertzy authored
324 By default, pg_search_scope uses the built-in {PostgreSQL text search}[http://www.postgresql.org/docs/current/static/textsearch-intro.html]. If you pass the :using option to pg_search_scope, you can choose alternative search techniques.
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
325
326 class Beer < ActiveRecord::Base
327 include PgSearch
f872548 @nertzy Update README to reflect change from :features to :using
nertzy authored
328 pg_search_scope :search_name, :against => :name, :using => [:tsearch, :trigram, :dmetaphone]
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
329 end
330
331 The currently implemented features are
332
825788c Fix links
Grant Hutchins & Rachel Heaton authored
333 * :tsearch - {Full text search}[http://www.postgresql.org/docs/current/static/textsearch-intro.html] (built-in with 8.3 and later, available as a contrib package for some earlier versions)
334 * :trigram - {Trigram search}[http://www.postgresql.org/docs/current/static/pgtrgm.html], which requires the trigram contrib package
335 * :dmetaphone - {Double Metaphone search}[http://www.postgresql.org/docs/9.0/static/fuzzystrmatch.html#AEN120188], which requires the fuzzystrmatch contrib package
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
336
337 ==== :tsearch (Full Text Search)
338
339 PostgreSQL's built-in full text search supports weighting, prefix searches, and stemming in multiple languages.
340
341 ===== Weighting
342 Each searchable column can be given a weight of "A", "B", "C", or "D". Columns with earlier letters are weighted higher than those with later letters. So, in the following example, the title is the most important, followed by the subtitle, and finally the content.
343
344 class NewsArticle < ActiveRecord::Base
345 include PgSearch
ab1827d Update README to remove Rails 2 and fix typos.
Grant Hutchins & Ian Zabel authored
346 pg_search_scope :search_full_text, :against => {
3fae8e9 Document dynamic search scopes
Grant Hutchins & Rachel Heaton authored
347 :title => 'A',
348 :subtitle => 'B',
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
349 :content => 'C'
350 }
351 end
3fae8e9 Document dynamic search scopes
Grant Hutchins & Rachel Heaton authored
352
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
353 You can also pass the weights in as an array of arrays, or any other structure that responds to #each and yields either a single symbol or a symbol and a weight. If you omit the weight, a default will be used.
354
355 class NewsArticle < ActiveRecord::Base
356 include PgSearch
ab1827d Update README to remove Rails 2 and fix typos.
Grant Hutchins & Ian Zabel authored
357 pg_search_scope :search_full_text, :against => [
3fae8e9 Document dynamic search scopes
Grant Hutchins & Rachel Heaton authored
358 [:title, 'A'],
359 [:subtitle, 'B'],
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
360 [:content, 'C']
361 ]
362 end
363
364 class NewsArticle < ActiveRecord::Base
365 include PgSearch
ab1827d Update README to remove Rails 2 and fix typos.
Grant Hutchins & Ian Zabel authored
366 pg_search_scope :search_full_text, :against => [
3fae8e9 Document dynamic search scopes
Grant Hutchins & Rachel Heaton authored
367 [:title, 'A'],
368 {:subtitle => 'B'},
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
369 :content
370 ]
371 end
372
9220f96 @nertzy Update README
nertzy authored
373 ===== :prefix (PostgreSQL 8.4 and newer only)
aaff48c Add documentation for :prefix
Grant Hutchins & Rachel Heaton authored
374
375 PostgreSQL's full text search matches on whole words by default. If you want to search for partial words, however, you can set :prefix to true. Since this is a :tsearch-specific option, you should pass it to :tsearch directly, as shown in the following example.
376
377 class Superhero < ActiveRecord::Base
378 include PgSearch
379 pg_search_scope :whose_name_starts_with,
380 :against => :name,
381 :using => {
382 :tsearch => {:prefix => true}
383 }
384 end
385
386 batman = Superhero.create :name => 'Batman'
387 batgirl = Superhero.create :name => 'Batgirl'
388 robin = Superhero.create :name => 'Robin'
389
390 Superhero.whose_name_starts_with("Bat") # => [batman, batgirl]
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
391
5df6e50 Documentation for :dictionary
Grant Hutchins & Rachel Heaton authored
392 ===== :dictionary
393
b28c311 @nertzy Add note to README about "simple" being the default dictionary for :tsea...
nertzy authored
394 PostgreSQL full text search also support multiple dictionaries for stemming. You can learn more about how dictionaries work by reading the {PostgreSQL documention}[http://www.postgresql.org/docs/current/static/textsearch-dictionaries.html]. If you use one of the language dictionaries, such as "english", then variants of words (e.g. "jumping" and "jumped") will match each other. If you don't want stemming, you should pick the "simple" dictionary which does not do any stemming. If you don't specify a dictionary, the "simple" dictionary will be used.
5df6e50 Documentation for :dictionary
Grant Hutchins & Rachel Heaton authored
395
396 class BoringTweet < ActiveRecord::Base
397 include PgSearch
398 pg_search_scope :kinda_matching,
399 :against => :text,
400 :using => {
401 :tsearch => {:dictionary => "english"}
402 }
403 pg_search_scope :literally_matching,
404 :against => :text,
405 :using => {
406 :tsearch => {:dictionary => "simple"}
407 }
408 end
409
410 sleepy = BoringTweet.create! :text => "I snoozed my alarm for fourteen hours today. I bet I can beat that tomorrow! #sleepy"
411 sleeping = BoringTweet.create! :text => "You know what I like? Sleeping. That's what. #enjoyment"
412 sleeper = BoringTweet.create! :text => "Have you seen Woody Allen's movie entitled Sleeper? Me neither. #boycott"
413
414 BoringTweet.kinda_matching("sleeping") # => [sleepy, sleeping, sleeper]
415 BoringTweet.literally_matching("sleeping") # => [sleeping]
416
68e2406 @nertzy Documentation for :normalization
nertzy authored
417 ===== :normalization
418
419 PostgreSQL supports multiple algorithms for ranking results against queries. For instance, you might want to consider overall document size or the distance between multiple search terms in the original text. This option takes an integer, which is passed directly to PostgreSQL. According to the latest {PostgreSQL documentation}[http://www.postgresql.org/docs/current/static/textsearch-controls.html], the supported algorithms are:
420
421 0 (the default) ignores the document length
422 1 divides the rank by 1 + the logarithm of the document length
423 2 divides the rank by the document length
424 4 divides the rank by the mean harmonic distance between extents
425 8 divides the rank by the number of unique words in document
426 16 divides the rank by 1 + the logarithm of the number of unique words in document
427 32 divides the rank by itself + 1
428
429 This integer is a bitmask, so if you want to combine algorithms, you can add their numbers together. (e.g. to use algorithms 1, 8, and 32, you would pass 1 + 8 + 32 = 41)
430
431 class BigLongDocument < ActiveRecord::Base
432 include PgSearch
433 pg_search_scope :regular_search,
434 :against => :text
435
436 pg_search_scope :short_search,
437 :against => :text,
438 :using => {
439 :tsearch => {:normalization => 2}
440 }
441
442 long = BigLongDocument.create!(:text => "Four score and twenty years ago")
443 short = BigLongDocument.create!(:text => "Four score")
444
445 BigLongDocument.regular_search("four score") #=> [long, short]
446 BigLongDocument.short_search("four score") #=> [short, long]
447
fc72793 @Ferdev Add :any_word option to :tsearch search feature
Ferdev authored
448 ===== :any_word
449
450 Setting this attribute to true will perform a search which will return all models containing any word in the search terms.
451
452 class Number < ActiveRecord::Base
453 include PgSearch
454 pg_search_scope :search_any_word,
455 :against => :text,
456 :using => {
457 :tsearch => {:any_word => true}
458 }
459
460 pg_search_scope :search_all_words,
461 :against => :text
462 end
463
464 one = Number.create! :text => 'one'
465 two = Number.create! :text => 'two'
466 three = Number.create! :text => 'three'
467
468 Number.search_any_word('one two three') # => [one, two, three]
469 Number.search_all_words('one two three') # => []
470
1e15f96 Documentation for :dmetaphone
Grant Hutchins & Rachel Heaton authored
471 ==== :dmetaphone (Double Metaphone soundalike search)
472
473 {Double Metaphone}[http://en.wikipedia.org/wiki/Double_Metaphone] is an algorithm for matching words that sound alike even if they are spelled very differently. For example, "Geoff" and "Jeff" sound identical and thus match. Currently, this is not a true double-metaphone, as only the first metaphone is used for searching.
474
7cdbced @nertzy Convert rake tasks into generators
nertzy authored
475 Double Metaphone support is currently available as part of the {fuzzystrmatch contrib package}[http://www.postgresql.org/docs/current/static/fuzzystrmatch.html] that must be installed before this feature can be used. In addition to the contrib package, you must install a utility function into your database. To generate and run a migration for this, run:
1e15f96 Documentation for :dmetaphone
Grant Hutchins & Rachel Heaton authored
476
7cdbced @nertzy Convert rake tasks into generators
nertzy authored
477 $ rails g pg_search:migration:dmetaphone
478 $ rake db:migrate
1e15f96 Documentation for :dmetaphone
Grant Hutchins & Rachel Heaton authored
479
480 The following example shows how to use :dmetaphone.
481
482 class Word < ActiveRecord::Base
483 include PgSearch
484 pg_search_scope :that_sounds_like,
485 :against => :spelling,
486 :using => :dmetaphone
487 end
488
489 four = Word.create! :spelling => 'four'
490 far = Word.create! :spelling => 'far'
491 fur = Word.create! :spelling => 'fur'
492 five = Word.create! :spelling => 'five'
493
494 Word.that_sounds_like("fir") # => [four, far, fur]
495
dd87a9e Documentation for :trigram
Grant Hutchins & Rachel Heaton authored
496 ==== :trigram (Trigram search)
497
498 Trigram search works by counting how many three-letter substrings (or "trigrams") match between the query and the text. For example, the string "Lorem ipsum" can be split into the following trigrams:
499
500 [" Lo", "Lor", "ore", "rem", "em ", "m i", " ip", "ips", "psu", "sum", "um ", "m "]
501
502 Trigram search has some ability to work even with typos and misspellings in the query or text.
503
825788c Fix links
Grant Hutchins & Rachel Heaton authored
504 Trigram support is currently available as part of the {pg_trgm contrib package}[http://www.postgresql.org/docs/current/static/pgtrgm.html] that must be installed before this feature can be used.
dd87a9e Documentation for :trigram
Grant Hutchins & Rachel Heaton authored
505
506
507 class Website < ActiveRecord::Base
508 include PgSearch
509 pg_search_scope :kinda_spelled_like,
510 :against => :name,
511 :using => :trigram
512 end
513
514 yahooo = Website.create! :name => "Yahooo!"
515 yohoo = Website.create! :name => "Yohoo!"
516 gogle = Website.create! :name => "Gogle"
517 facebook = Website.create! :name => "Facebook"
518
519 Website.kinda_spelled_like("Yahoo!") # => [yahooo, yohoo]
520
9220f96 @nertzy Update README
nertzy authored
521 === Ignoring accent marks (PostgreSQL 9.0 and newer only)
693149d Add documentation for :ignoring => :accents
Grant Hutchins & Rachel Heaton authored
522
523 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.
524
525 Ignoring accents uses the {unaccent contrib package}[http://www.postgresql.org/docs/current/static/unaccent.html] that must be installed before this feature can be used.
526
527
528 class SpanishQuestion < ActiveRecord::Base
529 include PgSearch
530 pg_search_scope :gringo_search,
531 :against => :word,
532 :ignoring => :accents
533 end
534
535 what = SpanishQuestion.create(:word => "Qué")
536 how_many = SpanishQuestion.create(:word => "Cuánto")
537 how = SpanishQuestion.create(:word => "Cómo")
538
539 SpanishQuestion.gringo_search("Que") # => [what]
540 SpanishQuestion.gringo_search("Cüåñtô") # => [how_many]
541
b068464 Add support for specifying a custom unaccent function
Daniel Fox & Grant Hutchins authored
542 Advanced users may wish to add indexes for the expressions that pg_search generates. Unfortunately, the unaccent function supplied by this contrib package is not indexable (as of PostgreSQL 9.1). Thus, you may want to write your own wrapper function and use it instead. This can be configured by calling the following code, perhaps in an initializer.
543
544 PgSearch.unaccent_function = "my_unaccent"
545
12ceb8d @krishicks Add tsvector_column option to pg_search_scope.
krishicks authored
546 === Using tsvector columns
547
548 PostgreSQL allows you the ability to search against a column with type tsvector instead of using an expression; this speeds up searching dramatically as it offloads creation of the tsvector that the tsquery is evaluated against.
549
550 To use this functionality you'll need to do a few things:
551
552 * Create a column of type tsvector that you'd like to search against. If you want to search using multiple search methods, for example tsearch and dmetaphone, you'll need a column for each.
553 * Create a trigger function that will update the column(s) using the expression appropriate for that type of search. See: http://www.postgresql.org/docs/current/static/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS
554 * Should you have any pre-existing data in the table, update the newly-created tsvector columns with the expression that your trigger function uses.
555 * Add the option to pg_search_scope, e.g:
556
7e8528b @nertzy Fix formatting of README for tsvector columns
nertzy authored
557 pg_search_scope :fast_content_search,
558 :against => :content,
559 :using => {
560 dmetaphone: {
561 tsvector_column: 'tsvector_content_dmetaphone'
562 },
563 tsearch: {
564 dictionary: 'english',
565 tsvector_column: 'tsvector_content_tsearch'
566 }
567 trigram: {} # trigram does not use tsvectors
12ceb8d @krishicks Add tsvector_column option to pg_search_scope.
krishicks authored
568 }
569
570 Please note that the :against column is only used when the tsvector_column is not present for the search type.
571
50b955f @nertzy Add the beginnings of a README
nertzy authored
572 == REQUIREMENTS
573
294b243 @nertzy Update requirements
nertzy authored
574 * ActiveRecord 3
575 * PostgreSQL
208fb15 @Peeja Link to wiki page for installing contrib packages.
Peeja authored
576 * {PostgreSQL contrib packages for certain features}[https://github.com/Casecommons/pg_search/wiki/Installing-Postgres-Contrib-Modules]
50b955f @nertzy Add the beginnings of a README
nertzy authored
577
63569b0 @nertzy Add an attribution to Aaron Patterson's gem
nertzy authored
578 == ATTRIBUTIONS
579
580 PgSearch would not have been possible without inspiration from
581 {texticle}[https://github.com/tenderlove/texticle]. Thanks to
582 {Aaron Patterson}[http://tenderlovemaking.com/]!
583
df22a4e Reword the README for the Pivotal Tracker project
Grant Hutchins & Sean Moon authored
584 == CONTRIBUTIONS AND FEEDBACK
c6b0427 Add links to Tracker and Google Group
Grant Hutchins & Sean Moon authored
585
df22a4e Reword the README for the Pivotal Tracker project
Grant Hutchins & Sean Moon authored
586 Welcomed! Feel free to join and contribute to our {public Pivotal Tracker project}[https://www.pivotaltracker.com/projects/228645] where we manage new feature ideas and bugs.
c6b0427 Add links to Tracker and Google Group
Grant Hutchins & Sean Moon authored
587
588 We also have a {Google Group}[http://groups.google.com/group/casecommons-dev] for discussing pg_search and other Case Commons open source projects.
589
30daa11 Remove extra colons from README
Grant Hutchins & Rachel Heaton authored
590 == LICENSE
50b955f @nertzy Add the beginnings of a README
nertzy authored
591
0511156 Adding more documentation
Grant Hutchins & Rachel Heaton authored
592 MIT
Something went wrong with that request. Please try again.