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

20Jan/104

Thinking Sphinx cannot find Sphinx

I was getting this error this morning after setting up my new laptop for the project I am working on:

1
2
3
4
5
6
7
8
9
10
11
12
13
sh: line 1:   326 Trace/BPT trap          indexer 2>&1
sh: line 1:   329 Trace/BPT trap          /usr/local/bin/indexer 2>&1
 
Sphinx cannot be found on your system. You may need to configure the following
settings in your config/sphinx.yml file:
  * bin_path
  * searchd_binary_name
  * indexer_binary_name
 
For more information, read the documentation:
http://freelancing-god.github.com/ts/en/advanced_config.html
rake aborted!
uninitialized constant MysqlCompat::MysqlRes

Everyone probably knows this, but I wild-goose-chased trying to figure out if I had a setting wrong in my sphinx.yml file for Thinking Sphinx this morning for like half an hour before I realized what Thinking Sphinx meant about "Sphinx cannot be found on your system." was that the MySQL Development headers weren't installed. I fixed this with a simple port install on Mac.

1
port install mysql5-devel

The more you know.

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

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