NAME

mongoid-fts.rb

DESCRIPTION

enable mongodb's new fulltext simply and quickly on your mongoid models.

mongodb's built-in fulltext is handy, but has several warts which make it difficult to use in real projects:

  • queries are boolean OR by default, meaning a user typing more and more specific search queries gets back less and less specific search results
  • lack of limit+offset on queries, making pagination a beast
  • lack of substring/fuzzy search
  • lack of literal search (find by id, uuid, etc. without hitting stemming/stopword functionality)
  • ability to search across collections

mongoid-fts smoothes over these warts, and more, for your mongoid 3 and 4 projects supporting:

  • pagination
  • strict literal searching (including stopwords)
  • cross models searching
  • index is automatically kept in sync
  • customize ranking with #to_search
  • fuzzy search (title and keywords included by default)

INSTALL


  gem 'mongoid-fts'


# required

  ~> bundle install

  ~> rake db:mongoid:create_indexes

# optional (this is done automatically)

  ~> rails runner 'Mongoid::FTS.enable!'

SYNOPSIS


# use the mixin method on your models to give them a 'search' method.  fts
# will attempt to guess which fields you mean to search.  title will be
# weighted most highly, then the array of keywords, then the fulltext of the
# model
#
  class A
    include Mongoid::Document
    include Mongoid::FTS::Able

    field(:title)
    field(:keywords, :type => Array)
    field(:fulltext)
  end

# if your fields are named like this you can certain override what's indexed
#

  class B
    include Mongoid::Document
    include Mongoid::FTS::Able

    field(:a)
    field(:b, :type => Array, :default => [])
    field(:c)

    def to_search
      {
        :literals => [id, sku],
        :title => a,
        :keywords => (b + ['foobar']),
        :fuzzy => [a, b],
        :fulltext => c
      }
    end
  end


# after this searching is pretty POLS
#

  A.create!(:title => 'foo', :body => 'cats')
  A.create!(:title => 'foo', :body => 'cat')

  p A.search('cat').size #=> 2

  p A.search(:literal => A.first.id).size #=> 1

# you can to cross-model searches like so
#
  p Mongoid::FTS.search('cat', :models => [A, B])
  p Mongoid::FTS.search('dog', :models => [A, B])

# pagination is supported

  A.search('cats').page(10).per(3)

# or 

  A.search('cats').paginate(:page => 10, :per => 3)


# handy to know

  Mongoid::FTS::Index.rebuild! # re-index every currently known object - not super effecient

  Mongoid::FTS::Index.reset!   # completely drop/create indexes - lose all objects

  Mongoid::FTS.index(model)    # add an object to the fts index

  Mongoid::FTS.unindex(model)  # remove and object from the fts index

regardless, the interface of this mixin is uber simple and should be quite future proof. as the mongodb teams moves search forward i'll track the new implementation and preserve the current interface. until it settles down, however, i'll resist adding new features.