mongoid-sphinx 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -23,49 +23,19 @@ and a MongoDB installation. Just add this to your Gemfile:
23
23
  No additional configuraton is needed for interfacing with MongoDB: Setup is
24
24
  done when Mongoid is able to talk to the MongoDB server.
25
25
 
26
- A proper "sphinx.conf" file and a script for retrieving index data have to
27
- be provided for interfacing with Sphinx: Sorry, no ThinkingSphinx like
28
- magic... :-) Depending on the amount of data, more than one index may be used
29
- and indexes may be consolidated from time to time.
30
-
31
- This is a sample configuration for a single "main" index:
32
-
33
- searchd {
34
- address = 0.0.0.0
35
- port = 3312
36
-
37
- log = ./sphinx/searchd.log
38
- query_log = ./sphinx/query.log
39
- pid_file = ./sphinx/searchd.pid
40
- }
41
-
42
- source mongoblog {
43
- type = xmlpipe2
44
-
45
- xmlpipe_command = rake sphinx:genxml --silent
46
- }
47
-
48
- index mongoblog {
49
- source = mongoblog
50
-
51
- charset_type = utf-8
52
- path = ./sphinx/sphinx_index_main
53
- }
54
-
55
- Notice the line "xmlpipe_command =". This is what the indexer runs to generate
56
- its input. You can change this to whatever works best for you, but I set it up as
57
- a rake task, with the following in `lib/tasks/sphinx.rake` .
58
-
59
- Here :fields is a list of fields to export. Performance tends to suffer if you export
60
- everything, so you'll probably want to just list the fields you're indexing.
61
-
62
- namespace :sphinx do
63
- task :genxml => :environment do
64
- MongoidSphinx::Indexer::XMLDocset.stream(Food)
65
- end
66
- end
26
+ ## Rake Tasks
27
+
28
+ MongoidSphinx can now generate your configs and control indexer and searchd through rake
29
+ tasks (many thanks to Pat Allen for his work on Thinking Sphinx here. Much of the code to
30
+ make this happen is right out of TS). Here is a list of the available rake tasks:
67
31
 
68
- This uses MongoDB cursor to better stream collection. Instead of offset. See: http://groups.google.com/group/mongodb-user/browse_thread/thread/35f01db45ea3b0bd/96ebc49b511a6b41?lnk=gst&q=skip#96ebc49b511a6b41
32
+ mongoid_sphinx:configure # creates a configuration file in congif/{environment}.sphinx.conf
33
+ mongoid_sphinx:index # indexes your data
34
+ mongoid_sphinx:start # starts searchd
35
+ mongoid_sphinx:stop # stops searchd
36
+ mongoid_sphinx:restart # stops then start searchd
37
+
38
+ There are also some shortcuts you can use. See lib/mongoid_sphinx/tasks.rb for the full list.
69
39
 
70
40
  ## Models
71
41
 
@@ -85,8 +55,12 @@ Sample:
85
55
 
86
56
  field :title
87
57
  field :body
58
+ field :created_at, :type => 'DateTime'
59
+ field :comment_count, :type => 'Integer'
88
60
 
89
- search_index :title, :body
61
+ search_index(:fields => [:title, :body],
62
+ :attributes => [:created_at, :comment_count],
63
+ :options => {:stopwords => "#{Rails.root}/config/sphinx/stopwords.txt"})
90
64
  end
91
65
 
92
66
  You must also create a config/sphinx.yml file with the host and port of your sphinxd process like so:
@@ -114,7 +88,7 @@ Samples:
114
88
 
115
89
  Post.search('first')
116
90
  => [...]
117
-
91
+
118
92
  post = Post.search('this is @title post').first
119
93
  post.title
120
94
  => "First Post"
@@ -129,6 +103,12 @@ document IDs but return the raw IDs instead.
129
103
  Sample:
130
104
 
131
105
  Post.search('my post', :limit => 100)
106
+
107
+ You can also specify filters based on attributes. Here is the format:
108
+
109
+ post = Post.search('first', :with => {:created_at => 1.day.ago..Time.now})
110
+ post = Post.search('first', :without => {:created_at => 1.day.ago..Time.now})
111
+ post = Post.search('first', :with => {:comment_count => [5,6]})
132
112
 
133
113
  ## Copyright
134
114
 
@@ -5,17 +5,156 @@ module MongoidSphinx
5
5
  class Configuration
6
6
  include Singleton
7
7
 
8
- attr_accessor :address, :port, :configuration
8
+ SourceOptions = %w( mysql_connect_flags mysql_ssl_cert mysql_ssl_key
9
+ mysql_ssl_ca sql_range_step sql_query_pre sql_query_post
10
+ sql_query_killlist sql_ranged_throttle sql_query_post_index unpack_zlib
11
+ unpack_mysqlcompress unpack_mysqlcompress_maxsize )
12
+
13
+ IndexOptions = %w( blend_chars charset_table charset_type charset_dictpath
14
+ docinfo enable_star exceptions expand_keywords hitless_words
15
+ html_index_attrs html_remove_elements html_strip index_exact_words
16
+ ignore_chars inplace_docinfo_gap inplace_enable inplace_hit_gap
17
+ inplace_reloc_factor inplace_write_factor min_infix_len min_prefix_len
18
+ min_stemming_len min_word_len mlock morphology ngram_chars ngram_len
19
+ ondisk_dict overshort_step phrase_boundary phrase_boundary_step preopen
20
+ stopwords stopwords_step wordforms )
21
+
22
+ attr_accessor :searchd_file_path, :model_directories, :indexed_models
23
+ attr_accessor :source_options, :index_options
24
+ attr_accessor :configuration, :controller
25
+
26
+ def initialize
27
+ @configuration = Riddle::Configuration.new
28
+ @configuration.searchd.pid_file = "#{Rails.root}/log/searchd.#{Rails.env}.pid"
29
+ @configuration.searchd.log = "#{Rails.root}/log/searchd.log"
30
+ @configuration.searchd.query_log = "#{Rails.root}/log/searchd.query.log"
31
+
32
+ @controller = Riddle::Controller.new @configuration, "#{Rails.root}/config/#{Rails.env}.sphinx.conf"
33
+
34
+ self.address = "127.0.0.1"
35
+ self.port = 9312
36
+ self.searchd_file_path = "#{Rails.root}/db/sphinx/#{Rails.env}"
37
+ self.model_directories = ["#{Rails.root}/app/models/"] + Dir.glob("#{Rails.root}/vendor/plugins/*/app/models/")
38
+ self.indexed_models = []
39
+
40
+ self.source_options = {
41
+ :type => "xmlpipe2"
42
+ }
43
+ self.index_options = {
44
+ :charset_type => "utf-8",
45
+ :morphology => "stem_en"
46
+ }
47
+
48
+ parse_config
49
+
50
+ self
51
+ end
9
52
 
10
53
  def client
11
54
  @configuration ||= parse_config
12
55
  Riddle::Client.new address, port
13
56
  end
14
57
 
58
+ def build(file_path=nil)
59
+ file_path ||= "#{self.config_file}"
60
+
61
+ @configuration.indexes.clear
62
+
63
+ MongoidSphinx.context.indexed_models.each do |model|
64
+ model = model.constantize
65
+ @configuration.indexes.concat model.to_riddle
66
+ end
67
+
68
+ open(file_path, "w") do |file|
69
+ file.write @configuration.render
70
+ end
71
+ end
72
+
73
+ def address
74
+ @address
75
+ end
76
+
77
+ def address=(address)
78
+ @address = address
79
+ @configuration.searchd.address = address
80
+ end
81
+
82
+ def port
83
+ @port
84
+ end
85
+
86
+ def port=(port)
87
+ @port = port
88
+ @configuration.searchd.port = port
89
+ end
90
+
91
+ def mem_limit
92
+ @mem_limit
93
+ end
94
+
95
+ def mem_limit=(mem_limit)
96
+ @mem_limit = mem_limit
97
+ @configuration.indexer.mem_limit = mem_limit
98
+ end
99
+
100
+ def pid_file
101
+ @configuration.searchd.pid_file
102
+ end
103
+
104
+ def pid_file=(pid_file)
105
+ @configuration.searchd.pid_file = pid_file
106
+ end
107
+
108
+ def searchd_log_file
109
+ @configuration.searchd.log
110
+ end
111
+
112
+ def searchd_log_file=(file)
113
+ @configuration.searchd.log = file
114
+ end
115
+
116
+ def query_log_file
117
+ @configuration.searchd.query_log
118
+ end
119
+
120
+ def query_log_file=(file)
121
+ @configuration.searchd.query_log = file
122
+ end
123
+
124
+ def config_file
125
+ @controller.path
126
+ end
127
+
128
+ def config_file=(file)
129
+ @controller.path = file
130
+ end
131
+
132
+ def bin_path
133
+ @controller.bin_path
134
+ end
135
+
136
+ def bin_path=(path)
137
+ @controller.bin_path = path
138
+ end
139
+
140
+ def searchd_binary_name
141
+ @controller.searchd_binary_name
142
+ end
143
+
144
+ def searchd_binary_name=(name)
145
+ @controller.searchd_binary_name = name
146
+ end
147
+
148
+ def indexer_binary_name
149
+ @controller.indexer_binary_name
150
+ end
151
+
152
+ def indexer_binary_name=(name)
153
+ @controller.indexer_binary_name = name
154
+ end
155
+
15
156
  private
16
157
 
17
- # Parse the config/sphinx.yml file - if it exists
18
- #
19
158
  def parse_config
20
159
  path = "#{Rails.root}/config/sphinx.yml"
21
160
  return unless File.exists?(path)
@@ -0,0 +1,62 @@
1
+ class MongoidSphinx::Context
2
+ attr_reader :indexed_models
3
+
4
+ def initialize(*models)
5
+ @indexed_models = []
6
+ end
7
+
8
+ def prepare
9
+ MongoidSphinx::Configuration.instance.indexed_models.each do |model|
10
+ add_indexed_model model
11
+ end
12
+
13
+ return unless indexed_models.empty?
14
+
15
+ load_models
16
+ end
17
+
18
+ def define_indexes
19
+ indexed_models.each { |model|
20
+ model.constantize.define_indexes
21
+ }
22
+ end
23
+
24
+ def add_indexed_model(model)
25
+ model = model.name if model.is_a?(Class)
26
+
27
+ indexed_models << model
28
+ indexed_models.uniq!
29
+ indexed_models.sort!
30
+ end
31
+
32
+ private
33
+
34
+ # Make sure all models are loaded - without reloading any that
35
+ # ActiveRecord::Base is already aware of (otherwise we start to hit some
36
+ # messy dependencies issues).
37
+ #
38
+ def load_models
39
+ MongoidSphinx::Configuration.instance.model_directories.each do |base|
40
+ Dir["#{base}**/*.rb"].each do |file|
41
+ model_name = file.gsub(/^#{base}([\w_\/\\]+)\.rb/, '\1')
42
+
43
+ next if model_name.nil?
44
+ next if ::ActiveRecord::Base.send(:descendants).detect { |model|
45
+ model.name == model_name.camelize
46
+ }
47
+
48
+ begin
49
+ model_name.camelize.constantize
50
+ rescue LoadError
51
+ model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
52
+ rescue NameError
53
+ next
54
+ rescue StandardError => err
55
+ STDERR.puts "Warning: Error loading #{file}:"
56
+ STDERR.puts err.message
57
+ STDERR.puts err.backtrace.join("\n"), ''
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,75 @@
1
+ module MongoidSphinx
2
+ class Index
3
+ attr_accessor :name, :model, :source
4
+
5
+ def initialize(model)
6
+ @name = self.class.name_for model
7
+ @model = model
8
+ @options = model.index_options
9
+ @source = Riddle::Configuration::XMLSource.new( "#{core_name}_0", config.source_options[:type])
10
+ @source.xmlpipe_command = "RAILS_ENV=#{Rails.env} script/rails runner '#{model.to_s}.sphinx_stream'"
11
+ end
12
+
13
+ def core_name
14
+ "#{name}_core"
15
+ end
16
+
17
+ def self.name_for(model)
18
+ model.name.underscore.tr(':/\\', '_')
19
+ end
20
+
21
+ def local_options
22
+ @options
23
+ end
24
+
25
+ def options
26
+ all_index_options = config.index_options.clone
27
+ @options.keys.select { |key|
28
+ MongoidSphinx::Configuration::IndexOptions.include?(key.to_s)
29
+ }.each { |key| all_index_options[key.to_sym] = @options[key] }
30
+ all_index_options
31
+ end
32
+
33
+ def to_riddle
34
+ indexes = [to_riddle_for_core]
35
+ indexes << to_riddle_for_distributed
36
+ end
37
+
38
+ private
39
+
40
+ def utf8?
41
+ options[:charset_type] == "utf-8"
42
+ end
43
+
44
+ def config
45
+ @config ||= MongoidSphinx::Configuration.instance
46
+ end
47
+
48
+ def to_riddle_for_core
49
+ index = Riddle::Configuration::Index.new core_name
50
+ index.path = File.join config.searchd_file_path, index.name
51
+
52
+ set_configuration_options_for_indexes index
53
+ index.sources << @source
54
+
55
+ index
56
+ end
57
+
58
+ def to_riddle_for_distributed
59
+ index = Riddle::Configuration::DistributedIndex.new name
60
+ index.local_indexes << core_name
61
+ index
62
+ end
63
+
64
+ def set_configuration_options_for_indexes(index)
65
+ config.index_options.each do |key, value|
66
+ method = "#{key}=".to_sym
67
+ index.send(method, value) if index.respond_to?(method)
68
+ end
69
+
70
+ options.each do |key, value|
71
+ index.send("#{key}=".to_sym, value) if MongoidSphinx::Configuration::IndexOptions.include?(key.to_s) && !value.nil?
72
+ end
73
+ end
74
+ end
75
+ end
@@ -17,15 +17,32 @@ module Mongoid
17
17
 
18
18
  cattr_accessor :search_fields
19
19
  cattr_accessor :search_attributes
20
+ cattr_accessor :index_options
20
21
  end
21
22
 
22
23
  module ClassMethods
24
+
23
25
  def search_index(options={})
24
26
  self.search_fields = options[:fields]
25
27
  self.search_attributes = {}
28
+ self.index_options = options[:options] || {}
26
29
  options[:attributes].each do |attrib|
27
30
  self.search_attributes[attrib] = SPHINX_TYPE_MAPPING[self.fields[attrib.to_s].type.to_s] || 'str2ordinal'
28
31
  end
32
+
33
+ MongoidSphinx.context.add_indexed_model self
34
+ end
35
+
36
+ def internal_sphinx_index
37
+ MongoidSphinx::Index.new(self)
38
+ end
39
+
40
+ def has_sphinx_indexes?
41
+ self.search_fields && self.search_fields.length > 0
42
+ end
43
+
44
+ def to_riddle
45
+ self.internal_sphinx_index.to_riddle
29
46
  end
30
47
 
31
48
  def sphinx_stream
@@ -0,0 +1,10 @@
1
+ require 'mongoid_sphinx'
2
+ require 'rails'
3
+
4
+ module MongoidSphinx
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ load File.expand_path('../tasks.rb', __FILE__)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,113 @@
1
+ require 'fileutils'
2
+
3
+ namespace :mongoid_sphinx do
4
+
5
+ desc "Output the current Mongoid Sphinx version"
6
+ task :version => :environment do
7
+ puts "Mongoid Sphinx v" + MongoidSphinx::VERSION
8
+ end
9
+
10
+ desc "Stop if running, then start a Sphinx searchd daemon using Mongoid Sphinx's settings"
11
+ task :running_start => :environment do
12
+ Rake::Task["mongoid_sphinx:stop"].invoke if sphinx_running?
13
+ Rake::Task["mongoid_sphinx:start"].invoke
14
+ end
15
+
16
+ desc "Start a Sphinx searchd daemon using Mongoid Sphinx's settings"
17
+ task :start => :environment do
18
+ config = MongoidSphinx::Configuration.instance
19
+
20
+ FileUtils.mkdir_p config.searchd_file_path
21
+ raise RuntimeError, "searchd is already running." if sphinx_running?
22
+
23
+ Dir["#{config.searchd_file_path}/*.spl"].each { |file| File.delete(file) }
24
+
25
+ config.controller.start
26
+
27
+ if sphinx_running?
28
+ puts "Started successfully (pid #{sphinx_pid})."
29
+ else
30
+ puts "Failed to start searchd daemon. Check #{config.searchd_log_file}"
31
+ end
32
+ end
33
+
34
+ desc "Stop Sphinx using Mongoid Sphinx's settings"
35
+ task :stop => :environment do
36
+ unless sphinx_running?
37
+ puts "searchd is not running"
38
+ else
39
+ config = MongoidSphinx::Configuration.instance
40
+ pid = sphinx_pid
41
+ config.controller.stop
42
+ puts "Stopped search daemon (pid #{pid})."
43
+ end
44
+ end
45
+
46
+ desc "Restart Sphinx"
47
+ task :restart => [:environment, :stop, :start]
48
+
49
+ desc "Generate the Sphinx configuration file using Mongoid Sphinx's settings"
50
+ task :configure => :environment do
51
+ config = MongoidSphinx::Configuration.instance
52
+ puts "Generating Configuration to #{config.config_file}"
53
+ config.build
54
+ end
55
+
56
+ desc "Index data for Sphinx using Mongoid Sphinx's settings"
57
+ task :index => :environment do
58
+ config = MongoidSphinx::Configuration.instance
59
+ unless ENV["INDEX_ONLY"] == "true"
60
+ puts "Generating Configuration to #{config.config_file}"
61
+ config.build
62
+ end
63
+
64
+ FileUtils.mkdir_p config.searchd_file_path
65
+ config.controller.index :verbose => true
66
+ end
67
+
68
+ desc "Reindex Sphinx without regenerating the configuration file"
69
+ task :reindex => :environment do
70
+ config = MongoidSphinx::Configuration.instance
71
+ FileUtils.mkdir_p config.searchd_file_path
72
+ puts config.controller.index
73
+ end
74
+
75
+ desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
76
+ task :rebuild => :environment do
77
+ Rake::Task["mongoid_sphinx:stop"].invoke if sphinx_running?
78
+ Rake::Task["mongoid_sphinx:index"].invoke
79
+ Rake::Task["mongoid_sphinx:start"].invoke
80
+ end
81
+ end
82
+
83
+ namespace :ms do
84
+ desc "Output the current Mongoid Sphinx version"
85
+ task :version => "mongoid_sphinx:version"
86
+ desc "Stop if running, then start a Sphinx searchd daemon using Mongoid Sphinx's settings"
87
+ task :run => "mongoid_sphinx:running_start"
88
+ desc "Start a Sphinx searchd daemon using Mongoid Sphinx's settings"
89
+ task :start => "mongoid_sphinx:start"
90
+ desc "Stop Sphinx using Mongoid Sphinx's settings"
91
+ task :stop => "mongoid_sphinx:stop"
92
+ desc "Index data for Sphinx using Mongoid Sphinx's settings"
93
+ task :in => "mongoid_sphinx:index"
94
+ task :index => "mongoid_sphinx:index"
95
+ desc "Reindex Sphinx without regenerating the configuration file"
96
+ task :reindex => "mongoid_sphinx:reindex"
97
+ desc "Restart Sphinx"
98
+ task :restart => "mongoid_sphinx:restart"
99
+ desc "Generate the Sphinx configuration file using Mongoid Sphinx's settings"
100
+ task :conf => "mongoid_sphinx:configure"
101
+ desc "Generate the Sphinx configuration file using Mongoid Sphinx's settings"
102
+ task :config => "mongoid_sphinx:configure"
103
+ desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
104
+ task :rebuild => "mongoid_sphinx:rebuild"
105
+ end
106
+
107
+ def sphinx_pid
108
+ MongoidSphinx.sphinx_pid
109
+ end
110
+
111
+ def sphinx_running?
112
+ MongoidSphinx.sphinx_running?
113
+ end
@@ -1,3 +1,3 @@
1
1
  module MongoidSphinx #:nodoc
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -2,5 +2,54 @@ require "mongoid"
2
2
  require "riddle"
3
3
 
4
4
  require 'mongoid_sphinx/configuration'
5
+ require 'mongoid_sphinx/context'
6
+ require 'mongoid_sphinx/index'
5
7
  require 'mongoid_sphinx/mongoid/identity'
6
- require 'mongoid_sphinx/mongoid/sphinx'
8
+ require 'mongoid_sphinx/mongoid/sphinx'
9
+ require 'mongoid_sphinx/railtie'
10
+
11
+ module MongoidSphinx
12
+
13
+ @@sphinx_mutex = Mutex.new
14
+ @@context = nil
15
+
16
+ def self.context
17
+ if @@context.nil?
18
+ @@sphinx_mutex.synchronize do
19
+ if @@context.nil?
20
+ @@context = MongoidSphinx::Context.new
21
+ @@context.prepare
22
+ end
23
+ end
24
+ end
25
+
26
+ @@context
27
+ end
28
+
29
+ def self.reset_context!
30
+ @@sphinx_mutex.synchronize do
31
+ @@context = nil
32
+ end
33
+ end
34
+
35
+ def self.pid_active?(pid)
36
+ !!Process.kill(0, pid.to_i)
37
+ rescue Errno::EPERM => e
38
+ true
39
+ rescue Exception => e
40
+ false
41
+ end
42
+
43
+ def self.sphinx_running?
44
+ !!sphinx_pid && pid_active?(sphinx_pid)
45
+ end
46
+
47
+ def self.sphinx_pid
48
+ if File.exists?(MongoidSphinx::Configuration.instance.pid_file)
49
+ File.read(MongoidSphinx::Configuration.instance.pid_file)[/\d+/]
50
+ else
51
+ nil
52
+ end
53
+ end
54
+
55
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-sphinx
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Hodgson
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-04 00:00:00 -05:00
18
+ date: 2011-01-12 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
23
  none: false
24
24
  requirements:
25
25
  - - "="
@@ -32,12 +32,12 @@ dependencies:
32
32
  - beta
33
33
  - 19
34
34
  version: 2.0.0.beta.19
35
- requirement: *id001
36
35
  type: :runtime
37
36
  name: mongoid
38
37
  prerelease: false
38
+ version_requirements: *id001
39
39
  - !ruby/object:Gem::Dependency
40
- version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
43
  - - ~>
@@ -48,10 +48,10 @@ dependencies:
48
48
  - 1
49
49
  - 0
50
50
  version: 1.1.0
51
- requirement: *id002
52
51
  type: :runtime
53
52
  name: riddle
54
53
  prerelease: false
54
+ version_requirements: *id002
55
55
  description: A full text indexing extension for MongoDB using Sphinx and Mongoid.
56
56
  email:
57
57
  - mhodgson@redbeard-tech.com
@@ -63,8 +63,12 @@ extra_rdoc_files: []
63
63
 
64
64
  files:
65
65
  - lib/mongoid_sphinx/configuration.rb
66
+ - lib/mongoid_sphinx/context.rb
67
+ - lib/mongoid_sphinx/index.rb
66
68
  - lib/mongoid_sphinx/mongoid/identity.rb
67
69
  - lib/mongoid_sphinx/mongoid/sphinx.rb
70
+ - lib/mongoid_sphinx/railtie.rb
71
+ - lib/mongoid_sphinx/tasks.rb
68
72
  - lib/mongoid_sphinx/version.rb
69
73
  - lib/mongoid_sphinx.rb
70
74
  - README.markdown