mongoid_fulltext 0.5.8 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - ruby-head
4
+
data/CHANGELOG.md ADDED
@@ -0,0 +1,133 @@
1
+ 0.6.0 (Next Release)
2
+ --------------------
3
+
4
+ * [#2](https://github.com/artsy/mongoid_fulltext/pull/2): Upgrade to Mongoid 3.0 - [@volmer](https://github.com/volmer).
5
+ * [#1](https://github.com/artsy/mongoid_fulltext/pull/1): Fix: downcase destroys non-latin strings - [@netoneko](https://github.com/netoneko).
6
+
7
+ 0.5.8 (3/8/2012)
8
+ ----------------
9
+
10
+ * Fix: do not CGI.unescape inside fulltext search - [@dblock](https://github.com/dblock).
11
+ * Refactored array filter API, allowing for overriding filter query method - [@ethul](https://github.com/ethul).
12
+ * Fix: check for the existence of the Mongoid.logger before calling it in case it was configured to false - [@AaronH](https://github.com/AaronH).
13
+ * Added install instructions to Readme - [@Nerian](https://github.com/Nerian).
14
+
15
+ 0.5.7 (1/11/2012)
16
+ -----------------
17
+
18
+ * Added `reindex_immediately` option to suppress automatic reindexing - [@joeyAghion](https://github.com/joeyAghion).
19
+ * Fix: treatment of word separators, adding newlines, tabs and dashes into the set of default word separators - [@aaw](https://github.com/aaw).
20
+
21
+ 0.5.4 (11/8/2011)
22
+ -----------------
23
+
24
+ * Made full word and prefix bumps inversely proportional to the length of the string - [@aaw](https://github.com/aaw).
25
+
26
+ 0.5.3 (11/8/2011)
27
+ -----------------
28
+
29
+ * Added an option to index short prefixes of words - [@aaw](https://github.com/aaw).
30
+
31
+ 0.5.2 (11/5/2011)
32
+ -----------------
33
+
34
+ * Added the ability to index full words that are less than the ngram length and not stop words - [@aaw](https://github.com/aaw).
35
+
36
+ 0.5.1 (11/2/2011)
37
+ -----------------
38
+
39
+ * Reducing the score for a full-word match (these used to be counted multiple times for multiple occurrences) and adding a list of stopwords to the config. Stopwords aren't given a score boost when matched as full words - [@aaw](https://github.com/aaw).
40
+ * Added UTF8 downcasing - [@zepplock](https://github.com/zepplock).
41
+
42
+ 0.5.0 (10/11/2011)
43
+ -----------------
44
+
45
+ * Fix: inconsistet scoring words with the same length as the ngram length - [@aaw](https://github.com/aaw).
46
+
47
+ 0.4.5 (10/5/2011)
48
+ -----------------
49
+
50
+ * Added `update_if` config option to control when index updates occur - [@nickhoffman](https://github.com/nickhoffman).
51
+
52
+ 0.4.4 (8/31/2011)
53
+ -----------------
54
+
55
+ * Added `remove_accents` - [@tdp2110](https://github.com/tdp2110).
56
+
57
+ 0.4.3 (8/3/2011)
58
+ ----------------
59
+
60
+ * Fix: including `Mongoid::FulltextSearch` and not using it causes created_indexes to fail - [@dblock](https://github.com/dblock).
61
+
62
+ 0.4.2 (6/28/2011)
63
+ -----------------
64
+
65
+ * Delay-creating indexes in sync with how Mongoid creates indexes on normal collections - [@dblock](https://github.com/dblock).
66
+
67
+ 0.4.1 (6/27/2011)
68
+ -----------------
69
+
70
+ * Using `Mongoid.logger` for logging - [@dblock](https://github.com/dblock).
71
+ * Changed `ensure_index` to index in the background, avoid blocking booting app - [@dblock](https://github.com/dblock).
72
+
73
+ 0.4.0 (6/19/2011)
74
+ -----------------
75
+
76
+ * Removing all use of map-reduce - [@aaw](https://github.com/aaw).
77
+ * Support class name with module for example (Module::ClassConstantName) - [@steverandy](https://github.com/steverandy).
78
+
79
+ 0.3.7 (6/7/2011)
80
+ ----------------
81
+
82
+ * Added support for updating model indexes in bulk - [@dblock](https://github.com/dblock).
83
+
84
+ 0.3.6 (5/27/2011)
85
+ -----------------
86
+
87
+ * Skipping words that are shorter than the n-gram - [@dblock](https://github.com/dblock).
88
+ * Added `index_full_words` - [@dblock](https://github.com/dblock).
89
+ * Keeping max score of ngram in the ngram hash - [@dblock](https://github.com/dblock).
90
+
91
+ 0.3.5 (5/25/2011)
92
+ -----------------
93
+
94
+ * Added index on document_id for faster remove - [@dblock](https://github.com/dblock).
95
+ * Addeda way to return scored results - [@dblock](https://github.com/dblock).
96
+
97
+ 0.3.4 (5/16/2011)
98
+ -----------------
99
+
100
+ * Added support for array filters - [@dblock](https://github.com/dblock).
101
+ * Added support for Ruby 1.8.7 - [@dbussink](https://github.com/dbussink).
102
+
103
+ 0.3.2 (4/19/2011)
104
+ -----------------
105
+
106
+ Exposing `update_ngram_index` and `remove_from_ngram_index` for fast bulk-updating the index - [@aaw](https://github.com/aaw).
107
+
108
+ 0.3.1 (4/14/2011)
109
+ -----------------
110
+
111
+ * Support for mongo versions >= 1.7.4 - [@aaw](https://github.com/aaw).
112
+
113
+ 0.3.0 (4/13/2011)
114
+ -----------------
115
+
116
+ * Adding the ability to define filters on an index - [@aaw](https://github.com/aaw).
117
+
118
+ 0.2.0 (4/13/2011)
119
+ -----------------
120
+
121
+ * Multiple indexes per model, removing internal indexes entirely - [@aaw](https://github.com/aaw).
122
+
123
+ 0.1.1 (4/11/2011)
124
+ -----------------
125
+
126
+ * Keep garbage in the index from blowing up `fulltext_search` - [@aaw](https://github.com/aaw).
127
+ * Indexing the results of `to_s` if no fields are provided - [@aaw](https://github.com/aaw).
128
+ * Adding a `before_destroy` callback for external indexes - [@aaw](https://github.com/aaw).
129
+
130
+ 0.1.0 (4/7/2011)
131
+ ----------------
132
+
133
+ * Initial public release - [@aaw](https://github.com/aaw).
data/Gemfile CHANGED
@@ -1,12 +1,10 @@
1
1
  source "http://rubygems.org"
2
2
 
3
+ gem "mongoid", "~> 3.0.1"
3
4
  gem "unicode_utils", "~> 1.0.0"
4
5
 
5
- # Add dependencies to develop your gem here.
6
- # Include everything needed to run rake, tests, features, etc.
7
- group :development do
8
- gem "mongoid", "~> 2.0.0"
9
- gem "bson_ext", "~> 1.5.2"
10
- gem "rspec", "~> 2.5.0"
11
- gem "jeweler", "~> 1.5.2"
6
+ group :development, :test do
7
+ gem "bundler"
8
+ gem "rspec", "~> 2.10.0"
9
+ gem "jeweler", "~> 1.8.3"
12
10
  end
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 by Artsy, Inc.
1
+ Copyright (c) 2011-2012 by Artsy, Inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
16
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
17
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
18
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- THE SOFTWARE.
19
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- Mongoid Fulltext Search
1
+ Mongoid Fulltext Search [![Build Status](https://secure.travis-ci.org/artsy/mongoid_fulltext.png)](http://travis-ci.org/artsy/mongoid_fulltext)
2
2
  =======================
3
3
 
4
4
  Full-text search using n-gram matching for the Mongoid ODM. Tested on MongoDB 1.6 and above, but
@@ -7,61 +7,78 @@ probably works on earlier versions as well.
7
7
  MongoDB currently has no native full-text search capabilities, so this gem is a good fit for cases
8
8
  where you want something a little less than a full-blown indexing service like Solr. mongoid_fulltext
9
9
  lets you do a fuzzy string search across relatively short strings, which makes it good for populating
10
- autocomplete boxes based on the display names of your Rails models but not appropriate for, say,
10
+ autocomplete boxes based on the display names of your Rails models but not appropriate for, say,
11
11
  indexing hundreds of thousands of HTML documents.
12
12
 
13
13
  Install
14
14
  --------------
15
15
 
16
- gem 'mongoid_fulltext'
16
+ Version 0.6.0 or newer of this gem requires Ruby 1.9.3 and Mongoid 3.0.
17
+ Use version 0.5.x for Mongoid 2.4.x and Ruby 1.8.7, 1.9.2 or 1.9.3.
18
+
19
+ For Ruby 1.8.7 and/or Mongoid 2.x use [mongoid_fulltext 0.5.x](https://github.com/artsy/mongoid_fulltext/tree/0.5-stable).
20
+
21
+ ``` ruby
22
+ gem 'mongoid_fulltext'
23
+ ```
17
24
 
18
25
  Some examples:
19
26
  --------------
20
-
27
+
21
28
  Suppose you have an `Artist` model and want to index each artist's name:
22
29
 
23
- class Artist
24
- include Mongoid::Document
25
- include Mongoid::FullTextSearch
30
+ ``` ruby
31
+ class Artist
32
+ include Mongoid::Document
33
+ include Mongoid::FullTextSearch
26
34
 
27
- field :first_name
28
- field :last_name
35
+ field :first_name
36
+ field :last_name
29
37
 
30
- def name
31
- [first_name, last_name].join(' ')
32
- end
38
+ def name
39
+ [first_name, last_name].join(' ')
40
+ end
33
41
 
34
- fulltext_search_in :name
35
- end
42
+ fulltext_search_in :name
43
+ end
44
+ ```
36
45
 
37
46
  The `fulltext_search_in` directive will index the full name of the artist, so now
38
47
  you can call:
39
48
 
40
- Artist.fulltext_search("vince vangogh")
49
+ ``` ruby
50
+ Artist.fulltext_search("vince vangogh")
51
+ ```
41
52
 
42
53
  which will return an array of the Artist instances that best match the search string. Most likely,
43
54
  Vincent van Gogh will be included in the results. You can index multiple fields with the same
44
55
  index, so we can get the same effect of our Artist index above using:
45
56
 
46
- class Artist
47
- include Mongoid::Document
48
- include Mongoid::FullTextSearch
57
+ ``` ruby
58
+ class Artist
59
+ include Mongoid::Document
60
+ include Mongoid::FullTextSearch
49
61
 
50
- field :first_name
51
- field :last_name
62
+ field :first_name
63
+ field :last_name
52
64
 
53
- fulltext_search_in :first_name, :last_name
54
- end
65
+ fulltext_search_in :first_name, :last_name
66
+ end
67
+ ```
55
68
 
56
69
  To restrict the number of results returned, pass the `:max_results` parameter to `fulltext_search`:
57
70
 
58
- Artist.fulltext_search("vince vangogh", { :max_results => 5 })
71
+ ``` ruby
72
+ Artist.fulltext_search("vince vangogh", { :max_results => 5 })
73
+ ```
59
74
 
60
75
  To return a pair of `[ result, score ]` instead of an array of results, pass the `:return_scores` parameter to `fulltext_search`:
61
76
 
62
- Artist.fulltext_search("vince vangogh", { :return_scores => true })
77
+ ``` ruby
78
+ Artist.fulltext_search("vince vangogh", { :return_scores => true })
79
+ ```
63
80
 
64
- The larger a score is, the better mongoid_fulltext thinks the match is. The scores have the following rough
81
+ The larger a score is, the better mongoid_fulltext thinks the match is. The scores have the following rough
65
82
  interpretation that you can use to make decisions about whether the match is good enough:
66
83
 
67
84
  * If a prefix of your query matches something indexed, or if your query matches a prefix of something
@@ -74,86 +91,98 @@ interpretation that you can use to make decisions about whether the match is goo
74
91
  If you don't specify a field to index, the default is the result of `to_s` called on the object.
75
92
  The following definition will index the first and last name of an artist:
76
93
 
77
- class Artist
78
- include Mongoid::Document
79
- include Mongoid::FullTextSearch
94
+ ``` ruby
95
+ class Artist
96
+ include Mongoid::Document
97
+ include Mongoid::FullTextSearch
80
98
 
81
- field :first_name
82
- field :last_name
99
+ field :first_name
100
+ field :last_name
83
101
 
84
- def to_s
85
- '%s %s' % [first_name, last_name]
86
- end
102
+ def to_s
103
+ '%s %s' % [first_name, last_name]
104
+ end
87
105
 
88
- fulltext_search_in
89
- end
106
+ fulltext_search_in
107
+ end
108
+ ```
90
109
 
91
110
  The full-text index is stored in a separate MongoDB collection in the same database as the
92
111
  models you're indexing. By default, the name of this collection is generated for you. Above,
93
112
  a collection named something like `mongoid_fulltext.index_artist_0` will be created to
94
- hold the index data. You can override this naming and provide your own collection name with
113
+ hold the index data. You can override this naming and provide your own collection name with
95
114
  the :index_name parameter:
96
115
 
97
- class Artwork
98
- include Mongoid::Document
99
- include Mongoid::FullTextSearch
116
+ ``` ruby
117
+ class Artwork
118
+ include Mongoid::Document
119
+ include Mongoid::FullTextSearch
100
120
 
101
- field :title
102
- fulltext_search_in :title, :index_name => 'mongoid_fulltext.foobar'
103
- end
121
+ field :title
122
+ fulltext_search_in :title, :index_name => 'mongoid_fulltext.foobar'
123
+ end
124
+ ```
104
125
 
105
126
  You can also create multiple indexes on a single model, in which case you'll want to
106
127
  provide index names:
107
128
 
108
- class Artwork
109
- include Mongoid::Document
110
- include Mongoid::FullTextSearch
129
+ ``` ruby
130
+ class Artwork
131
+ include Mongoid::Document
132
+ include Mongoid::FullTextSearch
111
133
 
112
- field :title
113
- field :artist_name
114
- field :gallery_name
115
- filed :gallery_address
134
+ field :title
135
+ field :artist_name
136
+ field :gallery_name
137
+ filed :gallery_address
116
138
 
117
- fulltext_search_in :title, :index_name => 'title_index'
118
- fulltext_search_in :artist_name, :index_name => 'artist_name_index'
119
- fulltext_search_in :gallery_name, :gallery_address, :index_name => 'gallery_index'
120
- end
139
+ fulltext_search_in :title, :index_name => 'title_index'
140
+ fulltext_search_in :artist_name, :index_name => 'artist_name_index'
141
+ fulltext_search_in :gallery_name, :gallery_address, :index_name => 'gallery_index'
142
+ end
143
+ ```
121
144
 
122
145
  The index names are helpful now because you'll have to specify which one you want to use when you
123
146
  call `fulltext_search`:
124
147
 
125
- Artwork.fulltext_search('warhol', :index => 'artist_name_index')
148
+ ``` ruby
149
+ Artwork.fulltext_search('warhol', :index => 'artist_name_index')
150
+ ```
126
151
 
127
152
  If you have multiple indexes specified and you don't supply a name to `fulltext_search`, the
128
153
  method call will raise an exception.
129
154
 
130
155
  If you're indexing multiple models, you may find that you need to combine results to create
131
156
  a single result set. For example, if both the `Artist` model and the `Artwork` model are
132
- indexed for full-text search, then to get results from both, you'd have to call
157
+ indexed for full-text search, then to get results from both, you'd have to call
133
158
  `Artist.fulltext_search` and `Artwork.fulltext_search` and combine the results yourself. If
134
159
  your intention is instead to get the top k results from both Artists and Artworks, you can
135
160
  merge both into a single index by using the same `:external_index` parameter:
136
161
 
137
- class Artwork
138
- include Mongoid::Document
139
- include Mongoid::FullTextSearch
162
+ ``` ruby
163
+ class Artwork
164
+ include Mongoid::Document
165
+ include Mongoid::FullTextSearch
140
166
 
141
- field :title
142
- fulltext_search_in :title, :index_name => 'artwork_and_artists'
143
- end
167
+ field :title
168
+ fulltext_search_in :title, :index_name => 'artwork_and_artists'
169
+ end
144
170
 
145
- class Artist
146
- include Mongoid::Document
147
- include Mongoid::FullTextSearch
171
+ class Artist
172
+ include Mongoid::Document
173
+ include Mongoid::FullTextSearch
148
174
 
149
- field :name
150
- fulltext_search_in :name, :index_name => 'artwork_and_artists'
151
- end
175
+ field :name
176
+ fulltext_search_in :name, :index_name => 'artwork_and_artists'
177
+ end
178
+ ```
152
179
 
153
180
  Now that these two models share the same external index collection, we can search them both through
154
181
  either model's `fulltext_search` method:
155
182
 
156
- Artwork.fulltext_search('picasso') # returns same results as Artist.fulltext_search('picasso')
183
+ ``` ruby
184
+ Artwork.fulltext_search('picasso') # returns same results as Artist.fulltext_search('picasso')
185
+ ```
157
186
 
158
187
  If you want to filter the results from full-text search, you set up filters when the indexes are
159
188
  defined. For example, suppose that in addition to wanting to use the `artwork_and_artists` index
@@ -162,59 +191,63 @@ for artists only and for artworks priced above $10,000. Instead of creating two
162
191
  attempting to filter the results after the query is run, we can specify the filter predicates
163
192
  at the time of index definition:
164
193
 
165
- class Artwork
166
- include Mongoid::Document
167
- include Mongoid::FullTextSearch
168
-
169
- field :title
170
- field :price
171
- fulltext_search_in :title, :index_name => 'artwork_and_artists',
172
- :filters => { :is_expensive => lambda { |x| x.price > 10000 },
173
- :has_long_name => lambda { |x| x.title.length > 20 }}
174
- end
175
-
176
- class Artist
177
- include Mongoid::Document
178
- include Mongoid::FullTextSearch
179
-
180
- field :name
181
- field :birth_year
182
- fulltext_search_in :name, :index_name => 'artwork_and_artists',
183
- :filters => { :born_before_1900 => lambda { |x| x.birth_year < 1900 },
184
- :has_long_name => lambda { |x| x.name.length > 20}}
185
- end
194
+ ``` ruby
195
+ class Artwork
196
+ include Mongoid::Document
197
+ include Mongoid::FullTextSearch
198
+
199
+ field :title
200
+ field :price
201
+ fulltext_search_in :title, :index_name => 'artwork_and_artists',
202
+ :filters => { :is_expensive => lambda { |x| x.price > 10000 },
203
+ :has_long_name => lambda { |x| x.title.length > 20 }}
204
+ end
205
+
206
+ class Artist
207
+ include Mongoid::Document
208
+ include Mongoid::FullTextSearch
209
+
210
+ field :name
211
+ field :birth_year
212
+ fulltext_search_in :name, :index_name => 'artwork_and_artists',
213
+ :filters => { :born_before_1900 => lambda { |x| x.birth_year < 1900 },
214
+ :has_long_name => lambda { |x| x.name.length > 20}}
215
+ end
216
+ ```
186
217
 
187
218
  After defining filters, you can query for results that match particular values of filters:
188
219
 
189
- # Only return artists born before 1900 that match 'foobar'
190
- Artist.fulltext_search('foobar', :born_before_1900 => true)
220
+ ``` ruby
221
+ # Only return artists born before 1900 that match 'foobar'
222
+ Artist.fulltext_search('foobar', :born_before_1900 => true)
191
223
 
192
- # Return artists or artworks that match 'foobar' and have short names
193
- Artist.fulltext_search('foobar', :has_long_name => false)
224
+ # Return artists or artworks that match 'foobar' and have short names
225
+ Artist.fulltext_search('foobar', :has_long_name => false)
194
226
 
195
- # Only return artworks with prices over 10000 that match 'mona lisa'
196
- Artwork.fulltext_search('mona lisa', :is_expensive => true)
227
+ # Only return artworks with prices over 10000 that match 'mona lisa'
228
+ Artwork.fulltext_search('mona lisa', :is_expensive => true)
197
229
 
198
- # Only return artworks with prices less than 10000 that match 'mona lisa'
199
- Artwork.fulltext_search('mona lisa', :is_expensive => false)
230
+ # Only return artworks with prices less than 10000 that match 'mona lisa'
231
+ Artwork.fulltext_search('mona lisa', :is_expensive => false)
232
+ ```
200
233
 
201
- Note that in all of the example queries above, supplying a filter that is defined on exactly
234
+ Note that in all of the example queries above, supplying a filter that is defined on exactly
202
235
  one of the models will restrict the search to results from that model only. For example,
203
236
  since `:is_expensive` is defined only on `Artwork`s, a call to `fulltext_search` with either
204
237
  `:is_expensive => true` or `:is_expensive => false` will return only `Artwork` results.
205
238
 
206
- You can specify multiple filters per index and per model. Each filter is a predicate that will
207
- be called on objects as they're inserted into the full-text index (any time the model is saved.)
208
- Filters are only called on instances of models they're defined on, so in the example above, the
209
- `is_expensive` filter is only applied to instances of `Artwork` and the `born_before_1900` filter
210
- is only applied to instances of `Artist`, although both filters can be used when querying from
211
- either model. The `has_long_name` filter, on the other hand, will return instances of both
239
+ You can specify multiple filters per index and per model. Each filter is a predicate that will
240
+ be called on objects as they're inserted into the full-text index (any time the model is saved.)
241
+ Filters are only called on instances of models they're defined on, so in the example above, the
242
+ `is_expensive` filter is only applied to instances of `Artwork` and the `born_before_1900` filter
243
+ is only applied to instances of `Artist`, although both filters can be used when querying from
244
+ either model. The `has_long_name` filter, on the other hand, will return instances of both
212
245
  `Artwork` and `Artist` since it's defined on each model.
213
246
 
214
247
  Filters shouldn't ever throw, but if they do, the filter is just ignored. If you apply filters to
215
248
  indexes that are on multiple fields, the filter is applied to each field and the filter result is
216
- the AND of all of the individual results for each of the fields. Finally, if a filter is defined
217
- but criteria for that filter aren't passed to `fulltext_search`, the result is as if the filter
249
+ the AND of all of the individual results for each of the fields. Finally, if a filter is defined
250
+ but criteria for that filter aren't passed to `fulltext_search`, the result is as if the filter
218
251
  had never been defined - you see both models that both pass and fail the filter in the results.
219
252
 
220
253
  Indexing Options
@@ -236,7 +269,7 @@ Additional indexing/query options can be used as parameters to `fulltext_search_
236
269
  Defaults to 1000. If you're seeing poor results, you can try increasing this value to consider
237
270
  more ngrams per query (changing this parameter does not require a re-index.) The amount of time
238
271
  a search takes is directly proportional to this parameter's value.
239
- * `remove_accents`: remove accents on accented characters, default is `true`.
272
+ * `remove_accents`: remove accents on accented characters, default is `true`.
240
273
  We strip the accents using [NFKD normalization](http://unicode-utils.rubyforge.org/UnicodeUtils.html#method-c-compatibility_decomposition)
241
274
  using an external library, `unicode_utils`.
242
275
  * `update_if`: controls whether or not the index will be updated. This can be set to a symbol,
@@ -247,46 +280,54 @@ Additional indexing/query options can be used as parameters to `fulltext_search_
247
280
  * When set to any other type of object, the document's index will not be updated.
248
281
  * `reindex_immediately`: whether models will be reindexed automatically upon saves or updates. Defaults to true. When set to false, the class-level `update_ngram_index` method can be called to perform reindexing.
249
282
 
283
+ If you work with Cyrillic texts, use this option: `:alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789абвгдежзиклмнопрстуфхцчшщъыьэюя'`.
284
+
250
285
  Array filters
251
286
  -------------
252
287
 
253
288
  A filter may also return an Array. Consider the following example.
254
289
 
255
- class Artist
256
- include Mongoid::Document
257
- include Mongoid::FullTextSearch
290
+ ``` ruby
291
+ class Artist
292
+ include Mongoid::Document
293
+ include Mongoid::FullTextSearch
258
294
 
259
- field :name
260
- field :exhibitions, as: Array, default: []
295
+ field :name
296
+ field :exhibitions, as: Array, default: []
261
297
 
262
- fulltext_search_in :name, :index_name => 'exhibited_artist',
263
- :filters => {
264
- :exhibitions => lambda { |artist| artist.exhibitions }
265
- }
266
- end
298
+ fulltext_search_in :name, :index_name => 'exhibited_artist',
299
+ :filters => {
300
+ :exhibitions => lambda { |artist| artist.exhibitions }
301
+ }
302
+ end
303
+ ```
267
304
 
268
305
  You can now find all artists that are at the Art Basel exhibition or all artists that have exhibited
269
306
  at both the Art Basel and the New York Armory exhibition.
270
307
 
271
- # All artists
272
- Artist.fulltext_search('foobar')
308
+ ``` ruby
309
+ # All artists
310
+ Artist.fulltext_search('foobar')
273
311
 
274
- # Artists at the Art Basel exhibition only
275
- Artist.fulltext_search('foobar', :exhibitions => [ "Art Basel" ])
312
+ # Artists at the Art Basel exhibition only
313
+ Artist.fulltext_search('foobar', :exhibitions => [ "Art Basel" ])
276
314
 
277
- # Artists at both the Art Basel and the New York Armory exhibition
278
- Artist.fulltext_search('foobar', :exhibitions => [ "Art Basel", "New York Armory" ])
315
+ # Artists at both the Art Basel and the New York Armory exhibition
316
+ Artist.fulltext_search('foobar', :exhibitions => [ "Art Basel", "New York Armory" ])
279
317
 
280
- # Note that the following explicit syntax may be used to achieve the
281
- # same result as above
282
- Artist.fulltext_search('foobar', :exhibitions => {:all => [ "Art Basel", "New York Armory" ]})
318
+ # Note that the following explicit syntax may be used to achieve the
319
+ # same result as above
320
+ Artist.fulltext_search('foobar', :exhibitions => {:all => [ "Art Basel", "New York Armory" ]})
321
+ ```
283
322
 
284
323
  If you want to find all artists that are at either the Art Basel or the
285
324
  New York Armory exhibition, then you may specify the `:any` operator in
286
325
  the filter.
287
326
 
288
- # Artists at either the Art Basel or the New York Armory exhibition
289
- Artist.fulltext_search('foobar', :exhibitions => {:any => [ "Art Basel", "New York Armory" ]})
327
+ ``` ruby
328
+ # Artists at either the Art Basel or the New York Armory exhibition
329
+ Artist.fulltext_search('foobar', :exhibitions => {:any => [ "Art Basel", "New York Armory" ]})
330
+ ```
290
331
 
291
332
  Note that `:all` and `:any` are currently the only supported operators
292
333
  for the array filters.
@@ -294,47 +335,67 @@ for the array filters.
294
335
  Building the index
295
336
  ------------------
296
337
 
297
- The fulltext index is built and maintained incrementally by hooking into `before_save` and
338
+ The fulltext index is built and maintained incrementally by hooking into `before_save` and
298
339
  `before_destroy` callbacks on each model that's being indexed. If you want to build an index
299
340
  on existing models, you can call the `update_ngram_index` method on the class or each instance:
300
341
 
301
- Artwork.update_ngram_index
302
- Artwork.find(id).update_ngram_index
342
+ ``` ruby
343
+ Artwork.update_ngram_index
344
+ Artwork.find(id).update_ngram_index
345
+ ```
303
346
 
304
347
  You can remove all or individual instances from the index with the `remove_from_ngram_index`
305
348
  method:
306
349
 
307
- Artwork.remove_from_ngram_index
308
- Artwork.find(id).remove_from_ngram_index
350
+ ``` ruby
351
+ Artwork.remove_from_ngram_index
352
+ Artwork.find(id).remove_from_ngram_index
353
+ ```
309
354
 
310
- The methods on the model level perform bulk removal operations and are therefore faster that
355
+ The methods on the model level perform bulk removal operations and are therefore faster that
311
356
  updating or removing records individually.
312
357
 
313
358
  If you need to control when the index is updated, provide the `update_if` option to
314
359
  `fulltext_search_in`, and set it to a symbol, string, or proc. Eg:
315
360
 
316
- # Only update the "age" index if the "age" field has changed.
317
- fulltext_search_in :age, :update_if => :age_changed?
361
+ ``` ruby
362
+ # Only update the "age" index if the "age" field has changed.
363
+ fulltext_search_in :age, :update_if => :age_changed?
318
364
 
319
- # Only update the "names" index if the "firstname" or "lastname" field has changed.
320
- fulltext_search_in :names, :update_if => "firstname_changed? || lastname_changed?"
365
+ # Only update the "names" index if the "firstname" or "lastname" field has changed.
366
+ fulltext_search_in :names, :update_if => "firstname_changed? || lastname_changed?"
321
367
 
322
- # Only update the "email" index if the "email" field ends with "gmail.com".
323
- fulltext_search_in :email, :update_if => Proc.new { |doc| doc.email.match /gmail.com\Z/ }
368
+ # Only update the "email" index if the "email" field ends with "gmail.com".
369
+ fulltext_search_in :email, :update_if => Proc.new { |doc| doc.email.match /gmail.com\Z/ }
370
+ ```
324
371
 
325
372
  Mongo Database Indexes
326
373
  ----------------------
327
374
 
328
375
  Mongoid provides an indexing mechanism on its models triggered by the `create_indexes` method.
329
376
  Mongoid_fulltext will hook into that behavior and create appropriate database indexes on its
330
- collections. These indexes are required for an efficient full text search.
377
+ collections. These indexes are required for an efficient full text search.
331
378
 
332
379
  Creating database indexes is typically done with the `db:mongoid:create_indexes` task.
333
380
 
334
- rake db:mongoid:create_indexes
381
+ ``` bash
382
+ rake db:mongoid:create_indexes
383
+ ```
335
384
 
336
385
  Running the specs
337
386
  -----------------
338
387
 
339
388
  To run the specs, execute `rake spec`. You need a local MongoDB instance to run the specs.
340
389
 
390
+ Contributing
391
+ ------------
392
+
393
+ Fork the project. Make your feature addition or bug fix with tests. Send a pull request. Bonus points for topic branches.
394
+
395
+ Copyright and License
396
+ ---------------------
397
+
398
+ MIT License, see [LICENSE](https://github.com/aaw/mongoid_fulltext/blob/master/LICENSE) for details.
399
+
400
+ (c) 2011-2012 [Art.sy Inc.](http://artsy.github.com)
401
+