Cory O'Daniel – These are just words Software development, thoughts, and randomness

7Jan/101

DataMapper 0.10+ Basic Sphinx Support

I needed sphinx support and I needed it now. Apparently dm-sphinx-adapter wasn't ported to dm 0.10. I started porting it, but I kind of felt like I was going down a rabbit whole. I will continue to work on it over the next couple days, in the meantime at Vokle we used this to get our fulltext on. Note, this is doing the fulltext search across all columns in your fulltext index. Its not doing cool matchers like :updated_at.gt yada-yada. It also doesn't implement a DataMapper Adapter, its a super hack, but it gets the job done for us.

Give me your two cents and stay tuned for a full blown adapter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
module DataMapper
  module Model
    def sphinx_setup(opts={})
      @_sphinx_index = opts[:index]
    end
 
    def search(_query_, opts={})
      sph_client = opts.delete(:client) || Riddle::Client.new(*SimpleSphinx.conf)
      sph_client.match_mode = opts.delete(:match_mode) || :extended
 
      sphinx_query = _query_.to_s.gsub(/[\(\)\|\-!@~"&\/]/){|char| "\\#{char}"}
 
      results   = sph_client.query(sphinx_query, @_sphinx_index || self.storage_names[:default].to_sym)
      matches   = results[:matches]
      ids       = matches.map{|match| match[:doc]}
 
      # Fetch
      self.all(opts.merge({:id => ids}))
    end
  end
end
 
class SimpleSphinx
  class << self
    def conf
      [server, port]
    end
    def server=(s)
      @_server = s
    end
 
    def port=(p)
      @_port = p
    end
    def server
      @_server || 'localhost'
    end
    def port
      @_port || 3312
    end
  end
end

Wanna use it?

1
2
3
4
5
6
7
8
9
10
# Your Model here
Person.sphinx_setup(:index => "indexName") #defaults to storage name
SimpleSphinx.server = "example.com"
SimpleSphinx.port = 3312
 
Person.search("cory") #=> DataMapper::Collection
 
# you can pass an additional hash of stuff you would pass to Model#all and this will be used to filter
# the result set down POST sphinx when its collecting data from datamapper
Person.search("cory", :limit => 10, :gender => :male)

You've got your sphinxter back. Congrats!

Post to Twitter Post to Digg Post to Facebook Post to Reddit Post to StumbleUpon

Comments (1) Trackbacks (0)
  1. Cory, thanks for making sphinx available to DM 0.10+ users.


Leave a comment


No trackbacks yet.