Skip to content

christopher-fuller/mongodb_fulltext_search

Repository files navigation

mongodb_fulltext_search

A gem that adds fulltext search capability to Mongoid or MongoMapper documents. The MongoDB aggregation framework is utilized to perform searches quickly and efficiently.

Prerequisites

Rails must be configured to use either Mongoid or MongoMapper and MongoDB version 2.1.0 (or higher) is required.

Please get in touch if you’d like to see added support for another MongoDB object mapper (ODM).

Installation

$ gem install mongodb_fulltext_search

Rails Configuration

Add to Gemfile:

gem 'mongodb_fulltext_search'

Indexes

This gem implements indexes specifically for the fulltext search.

The fulltext indexes are maintained automatically via the before_save and before_destroy callbacks on models, however you MUST run the rake task (below) to rebuild the indexes any time your models change.

The indexes are implemented as MongoDB collections (since MongoDB’s built-in indexes do not currently support fulltext search), therefore the fulltext indexes are actually “index collections”. The “index collections” are stored in the same database that the models are persisted to.

The “index collections” benefit from using MongoDB indexes themselves and have MongoDB indexes defined via the underlying ODM, therefore be sure to create the indexes following the instructions for the ODM you are using.

With Mongoid for example, use the normal rake command rake db:mongoid:create_indexes. With MongoMapper for example, the indexes should be created automatically by default.

For the remainder of the documentation, the “index collections” will now simply be referred to as “indexes”.

Examples

Mongoid example:

class Widget

  include Mongoid::Document
  include Mongoid::FullTextSearch

  field :desc, :type => String
  field :tags, :type => Array

  fulltext_search_in :desc

end

MongoMapper example:

class Widget

  include MongoMapper::Document
  include MongoMapper::FullTextSearch

  key :desc, String
  key :tags, Array

  fulltext_search_in :desc

end

Or index multiple attributes together:

fulltext_search_in :desc, :tags

Or index virtual attributes:

fulltext_search_in :desc_and_tags

def desc_and_tags
  [ desc ] + tags
end

NOTE: All attributes (and virtual attributes) supplied to fulltext_search_in must return either a string or an array of strings.

Performing Searches

In controllers, perform searches with:

@widgets = Widget.fulltext_search params[:search_query]

After fulltext searches are performed, access scores via a fulltext_search_score attribute on models:

@widgets.each { |widget| widget.fulltext_search_score }

Multiple Indexes

It is possible to create more than one index on a model:

fulltext_search_in :desc, :index => 'desc_index'
fulltext_search_in :tags, :index => 'tags_index'

In this case, you MUST specify an index when performing a search:

@widgets = Widget.fulltext_search params[:search_query], :index => 'desc_index'

or

@widgets = Widget.fulltext_search params[:search_query], :index => 'tags_index'

NOTE: An ArgumentError exception will be raised if multiple indexes exist but an index is not specified.

Options

To match partial words, turn off exact matching:

@widgets = Widget.fulltext_search params[:search_query], :exact => false

By default, results are limited to 20 models but you can specify a limit when searching:

@widgets = Widget.fulltext_search params[:search_query], :limit => 10

And you can also specify an offset:

@widgets = Widget.fulltext_search params[:search_query], :offset => 20

To return document identifiers and search scores as a Hash (instead of the returning the model objects):

@scores = Widget.fulltext_search params[:search_query], :return_scores => true
@scores.each { |id, score| id + ': ' + score }

Normalization

Strings are normalized using normalize(:kd) (for queries and also indexes), so for example resumé and resume would match.

Stop Words

Stop words (i.e. blacklisted words) can be specified in a YAML config file.

To generate a config file with a default set of stop words:

$ rails g mongodb_fulltext_search:config

The default stop words are:

a, an, and, are, as, at, be, but, by, for, if, in, into, is, it, no, not, of, on, or, such, that, the, their, then, there, these, they, this, to, was, will, with

Rake Tasks

To rebuild indexes for all models:

$ rake db:mongo:rebuild_fulltext_search_indexes

To rebuild indexes for one model:

$ rake db:mongo:rebuild_fulltext_search_indexes[Widget]

NOTE: The indexes are maintained automatically via the before_save and before_destroy callbacks on models, however you MUST run this rake task any time your models change.

To Do

  • Filtered indexes

  • Shared indexes

Copyright © 2012 Christopher Fuller. See MIT-LICENSE for details.

About

A gem that adds fulltext search capability to Mongoid or MongoMapper documents. The MongoDB aggregation framework is utilized to perform searches quickly and efficiently.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages