Lunar
A minimalistic search index implemented using Redis, taking advantage of its
powerful sorted sets
and the ability to do set intersection and union.
Results are sorted by their word score, which is stored as the score in the Redis sorted set.
Examples
class Item < Ohm::Model
attribute :name
attribute :description
protected
def write
super
index
end
def index
Lunar::Index.create 'Item' do |i|
i.key id
i.attr :name, name
i.attr :description, description
end
# You can also do this, no problem
Lunar::Index.create Item do |i|
i.key id
i.attr :name, name
i.attr :description, description
end
# Or to avoid name ties...
Lunar::Index.create self.class do |i|
i.key id
i.attr :name, name
i.attr :description, description
end
Lunar::Index.create Item do |i|
i.key id
i.fuzzy :name, name # this has a 100 character limit on name
# for performance reasons
i.integer :cost, cost
i.float :voting_quotient, voting_quotient
end
end
end
# Searching...
# You can just straight out search keywords
Lunar.search(Item, "iphone")
# Or opt to filter by field
Lunar.search(Item, :name => "iphone", :description => "mobile")
# For fuzzy declared fields you can currently only search
# using a fuzzy strategy exclusively, e.g.
Lunar.search(Item, :fuzzy => { :name => "i" })
# i, ip, iph, ipho, iphone, 3, 3g, 3gs all would match 'iPhone 3Gs'
# For integer / float types, you can do range searches on them e.g.
Lunar.search(Item, :cost => 300..500, :voting_quotient => 10..20)
# Or using the pagination gem with this:
@items = Lunar.search(Item, "iphone")
paginate @items, :per_page => 10, :page => 1
# If you want to be cheap about CPU cycles you can increase the
# default `:ttl` of search results (which is 30)
# Somewhere in config/initializers or init.rb, you decide...
Lunar.ttl = 300 # search results would be the same for 5 minutes.
# for high write public sites, this may be a good
# option as people don't really expect their stuff to
# be searchable right away on public content sites.