dm-sphinx-adapter 0.5 → 0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +5 -0
- data/Manifest.txt +12 -19
- data/README.txt +20 -41
- data/Rakefile +2 -3
- data/dm-sphinx-adapter.gemspec +6 -9
- data/lib/dm-sphinx-adapter.rb +14 -11
- data/lib/dm-sphinx-adapter/adapter.rb +36 -62
- data/lib/dm-sphinx-adapter/attribute.rb +48 -3
- data/lib/riddle.rb +28 -0
- data/lib/riddle/client.rb +619 -0
- data/lib/riddle/client/filter.rb +53 -0
- data/lib/riddle/client/message.rb +65 -0
- data/lib/riddle/client/response.rb +84 -0
- data/test/files/model.rb +23 -0
- data/test/files/mysql5.sphinx.conf +97 -0
- data/test/files/mysql5.sql +26 -0
- data/test/helper.rb +51 -0
- data/test/test_adapter.rb +74 -28
- data/test/test_attribute.rb +36 -0
- data/test/test_index.rb +30 -0
- data/test/test_query.rb +47 -32
- data/test/test_resource.rb +17 -0
- metadata +18 -41
- data/lib/dm-sphinx-adapter/client.rb +0 -109
- data/lib/dm-sphinx-adapter/config.rb +0 -122
- data/lib/dm-sphinx-adapter/config_parser.rb +0 -71
- data/test/files/dm_sphinx_adapter_test.sql +0 -21
- data/test/files/resource_explicit.rb +0 -25
- data/test/files/resource_resource.rb +0 -19
- data/test/files/resource_searchable.rb +0 -16
- data/test/files/resource_storage_name.rb +0 -11
- data/test/files/resource_vanilla.rb +0 -7
- data/test/files/sphinx.conf +0 -78
- data/test/test_adapter_explicit.rb +0 -48
- data/test/test_adapter_resource.rb +0 -25
- data/test/test_adapter_searchable.rb +0 -23
- data/test/test_adapter_vanilla.rb +0 -46
- data/test/test_client.rb +0 -31
- data/test/test_config.rb +0 -75
- data/test/test_config_parser.rb +0 -29
- data/test/test_type_attribute.rb +0 -8
- data/test/test_type_index.rb +0 -8
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -7,27 +7,20 @@ dm-sphinx-adapter.gemspec
|
|
7
7
|
lib/dm-sphinx-adapter.rb
|
8
8
|
lib/dm-sphinx-adapter/adapter.rb
|
9
9
|
lib/dm-sphinx-adapter/attribute.rb
|
10
|
-
lib/dm-sphinx-adapter/client.rb
|
11
|
-
lib/dm-sphinx-adapter/config.rb
|
12
|
-
lib/dm-sphinx-adapter/config_parser.rb
|
13
10
|
lib/dm-sphinx-adapter/index.rb
|
14
11
|
lib/dm-sphinx-adapter/query.rb
|
15
12
|
lib/dm-sphinx-adapter/resource.rb
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
test/files/
|
22
|
-
test/files/sphinx.conf
|
13
|
+
lib/riddle.rb
|
14
|
+
lib/riddle/client.rb
|
15
|
+
lib/riddle/client/filter.rb
|
16
|
+
lib/riddle/client/message.rb
|
17
|
+
lib/riddle/client/response.rb
|
18
|
+
test/files/model.rb
|
19
|
+
test/files/mysql5.sphinx.conf
|
20
|
+
test/files/mysql5.sql
|
21
|
+
test/helper.rb
|
23
22
|
test/test_adapter.rb
|
24
|
-
test/
|
25
|
-
test/
|
26
|
-
test/test_adapter_searchable.rb
|
27
|
-
test/test_adapter_vanilla.rb
|
28
|
-
test/test_client.rb
|
29
|
-
test/test_config.rb
|
30
|
-
test/test_config_parser.rb
|
23
|
+
test/test_attribute.rb
|
24
|
+
test/test_index.rb
|
31
25
|
test/test_query.rb
|
32
|
-
test/
|
33
|
-
test/test_type_index.rb
|
26
|
+
test/test_resource.rb
|
data/README.txt
CHANGED
@@ -11,15 +11,13 @@ A DataMapper Sphinx adapter.
|
|
11
11
|
== Dependencies
|
12
12
|
|
13
13
|
* dm-core ~> 0.9.7
|
14
|
-
* riddle ~> 0.9
|
15
|
-
* daemon_controller ~> 0.2 (optional)
|
16
14
|
* dm-is-searchable ~> 0.9.7 (optional)
|
17
15
|
|
18
16
|
I'd recommend using the dm-more plugin dm-is-searchable instead of fetching the document id's yourself.
|
19
17
|
|
20
18
|
== Install
|
21
19
|
|
22
|
-
* Via git: git clone git://github.com/shanna/
|
20
|
+
* Via git: git clone git://github.com/shanna/dm-sphinx-adapter.git
|
23
21
|
* Via gem: gem install shanna-dm-sphinx-adapter -s http://gems.github.com
|
24
22
|
|
25
23
|
== Synopsis
|
@@ -27,9 +25,10 @@ I'd recommend using the dm-more plugin dm-is-searchable instead of fetching the
|
|
27
25
|
DataMapper uses URIs or a connection has to connect to your data-stores. In this case the sphinx search daemon
|
28
26
|
<tt>searchd</tt>.
|
29
27
|
|
30
|
-
On its own this adapter will only return an array of document hashes when queried. The DataMapper library
|
31
|
-
|
32
|
-
preference is to use this adapter in tandem with dm-is-searchable
|
28
|
+
On its own this adapter will only return an array of document hashes when queried. The DataMapper library
|
29
|
+
<tt>dm-is-searchable</tt> however provides a common interface to search one adapter and load documents from another. My
|
30
|
+
preference is to use this adapter in tandem with <tt>dm-is-searchable</tt>. See further examples in the synopsis for
|
31
|
+
usage with <tt>dm-is-searchable</tt>.
|
33
32
|
|
34
33
|
Like all DataMapper adapters you can connect with a Hash or URI.
|
35
34
|
|
@@ -41,7 +40,6 @@ The breakdown is:
|
|
41
40
|
- adapter Must be :sphinx
|
42
41
|
- host Hostname (default: localhost)
|
43
42
|
- port Optional port number (default: 3312)
|
44
|
-
- config Optional but strongly recommended path to sphinx config file.
|
45
43
|
|
46
44
|
Alternatively supply a Hash:
|
47
45
|
DataMapper.setup(:search, {
|
@@ -49,7 +47,6 @@ Alternatively supply a Hash:
|
|
49
47
|
:config => './sphinx.conf' # optional. Recommended though.
|
50
48
|
:host => 'localhost', # optional. Default: localhost
|
51
49
|
:port => 3312 # optional. Default: 3312
|
52
|
-
:managed => true # optional. Self managed searchd server using daemon_controller.
|
53
50
|
}
|
54
51
|
|
55
52
|
=== DataMapper
|
@@ -76,14 +73,16 @@ Alternatively supply a Hash:
|
|
76
73
|
IsSearchable is a DataMapper plugin that provides a common search interface when searching from one adapter and reading
|
77
74
|
documents from another.
|
78
75
|
|
79
|
-
IsSearchable will read resources from your
|
80
|
-
|
81
|
-
mapping the resulting document id's from a search with your
|
82
|
-
your
|
76
|
+
IsSearchable will read resources from your <tt>:default</tt> repository on behalf of a search adapter such as
|
77
|
+
<tt>dm-sphinx-adapter</tt> and <tt>dm-ferret-adapter</tt>. This saves some of the grunt work (as shown in the previous
|
78
|
+
example) by mapping the resulting document id's from a search with your <tt>:search</tt> adapter into a suitable
|
79
|
+
<tt>#first</tt> or <tt>#all</tt> query for your <tt>:default</tt> repository.
|
83
80
|
|
84
|
-
IsSearchable adds a single class method to your resource. The first argument is a
|
85
|
-
conditions to pass to your search adapter (in this case
|
86
|
-
DataMapper::Query conditions can also be passed and will be appended to the
|
81
|
+
IsSearchable adds a single class method to your resource. The first argument is a <tt>Hash</tt> of
|
82
|
+
<tt>DataMapper::Query</tt> conditions to pass to your search adapter (in this case <tt>dm-sphinx-adapter</tt>). An
|
83
|
+
optional second <tt>Hash</tt> of <tt>DataMapper::Query</tt> conditions can also be passed and will be appended to the
|
84
|
+
query on your <tt>:default</tt> database. This can be handy if you need to add extra exclusions that aren't possible
|
85
|
+
using <tt>dm-sphinx-adapter</tt> such as <tt>#gt</tt> or <tt>#lt</tt> conditions.
|
87
86
|
|
88
87
|
require 'rubygems'
|
89
88
|
require 'dm-core'
|
@@ -140,7 +139,6 @@ For finer grained control you can include DataMapper::SphinxResource. For instan
|
|
140
139
|
and sort, include or exclude by attributes defined in your sphinx configuration:
|
141
140
|
|
142
141
|
class Item
|
143
|
-
include DataMapper::Resource # Optional, included by SphinxResource if you leave it out yourself.
|
144
142
|
include DataMapper::SphinxResource
|
145
143
|
property :id, Serial
|
146
144
|
property :name, String
|
@@ -161,28 +159,16 @@ and sort, include or exclude by attributes defined in your sphinx configuration:
|
|
161
159
|
|
162
160
|
== Sphinx Configuration
|
163
161
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
DataMapper.setup(:search, :adapter => 'sphinx', :config => '/path/to/sphinx.conf')
|
168
|
-
DataMapper.setup(:search, 'sphinx://localhost/path/to/sphinx.conf')
|
169
|
-
|
170
|
-
If your sphinx.conf lives in either of the default locations /usr/local/etc/sphinx.conf or ./sphinx.conf then you
|
171
|
-
only need to supply:
|
172
|
-
|
173
|
-
DataMapper.setup(:search, :adapter => 'sphinx')
|
162
|
+
No limitations, restrictions or requirement are imposed on your sphinx configuration. The adapter will not generate nor
|
163
|
+
overwrite your finely crafted config file.
|
174
164
|
|
175
165
|
== Searchd
|
176
166
|
|
177
|
-
|
178
|
-
or whatever in production. Use the Hash form of DataMapper#setup and supply the option :managed with a true value and
|
179
|
-
daemon_controller will start searchd on demand.
|
167
|
+
To keep things simple, this adapter does not manage your sphinx server. Try one of these fine offerings:
|
180
168
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
The daemon_controller library can be found only on github, not rubyforge.
|
185
|
-
See http://github.com/FooBarWidget/daemon_controller/tree/master
|
169
|
+
* god[http://god.rubyforge.org]
|
170
|
+
* daemon_controller[http://github.com/FooBarWidget/daemon_controller/tree/master]
|
171
|
+
* monit[http://www.tildeslash.com/monit]
|
186
172
|
|
187
173
|
== Indexer and Live(ish) updates.
|
188
174
|
|
@@ -195,13 +181,6 @@ For reliable live(ish) updates in a main + delta scheme it's probably best you s
|
|
195
181
|
Andrew (Shodan) Aksyonoff of Sphinx suggests a cronjob or alternatively if you need even less lag to "run indexer in
|
196
182
|
an endless loop, with a few seconds of sleep in between to allow searchd some headroom to pick up the changes".
|
197
183
|
|
198
|
-
== Todo
|
199
|
-
|
200
|
-
* Loads of documentation. Most of it is unchecked YARD at the moment.
|
201
|
-
* Add DataMapper::Adapters::Sphinx::Client#attribute_set to allow attribute modification on one or more indexes. It's
|
202
|
-
the only thing missing if you understand the pitfalls and still want to add thinking-sphinx like delta indexing to
|
203
|
-
your resource.
|
204
|
-
|
205
184
|
== Contributing
|
206
185
|
|
207
186
|
Go nuts. Just send me a pull request (github or otherwise) when you are happy with your code.
|
data/Rakefile
CHANGED
@@ -3,11 +3,10 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
5
|
|
6
|
-
Hoe.new('dm-sphinx-adapter', '0.
|
6
|
+
Hoe.new('dm-sphinx-adapter', '0.6') do |p|
|
7
7
|
p.developer('Shane Hanna', 'shane.hanna@gmail.com')
|
8
8
|
p.extra_deps = [
|
9
|
-
['dm-core', '~> 0.9.7']
|
10
|
-
['riddle', '~> 0.9']
|
9
|
+
['dm-core', '~> 0.9.7']
|
11
10
|
]
|
12
11
|
end
|
13
12
|
|
data/dm-sphinx-adapter.gemspec
CHANGED
@@ -2,23 +2,23 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{dm-sphinx-adapter}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.6"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Shane Hanna"]
|
9
|
-
s.date = %q{2008-12-
|
9
|
+
s.date = %q{2008-12-13}
|
10
10
|
s.description = %q{A DataMapper Sphinx adapter.}
|
11
11
|
s.email = ["shane.hanna@gmail.com"]
|
12
12
|
s.extra_rdoc_files = ["History.txt", "LICENCE.txt", "Manifest.txt", "README.txt"]
|
13
|
-
s.files = ["History.txt", "LICENCE.txt", "Manifest.txt", "README.txt", "Rakefile", "dm-sphinx-adapter.gemspec", "lib/dm-sphinx-adapter.rb", "lib/dm-sphinx-adapter/adapter.rb", "lib/dm-sphinx-adapter/attribute.rb", "lib/dm-sphinx-adapter/
|
13
|
+
s.files = ["History.txt", "LICENCE.txt", "Manifest.txt", "README.txt", "Rakefile", "dm-sphinx-adapter.gemspec", "lib/dm-sphinx-adapter.rb", "lib/dm-sphinx-adapter/adapter.rb", "lib/dm-sphinx-adapter/attribute.rb", "lib/dm-sphinx-adapter/index.rb", "lib/dm-sphinx-adapter/query.rb", "lib/dm-sphinx-adapter/resource.rb", "lib/riddle.rb", "lib/riddle/client.rb", "lib/riddle/client/filter.rb", "lib/riddle/client/message.rb", "lib/riddle/client/response.rb", "test/files/model.rb", "test/files/mysql5.sphinx.conf", "test/files/mysql5.sql", "test/helper.rb", "test/test_adapter.rb", "test/test_attribute.rb", "test/test_index.rb", "test/test_query.rb", "test/test_resource.rb"]
|
14
14
|
s.has_rdoc = true
|
15
|
-
s.homepage = %q{http://rubyforge.org
|
15
|
+
s.homepage = %q{http://dm-sphinx.rubyforge.org}
|
16
16
|
s.rdoc_options = ["--main", "README.txt"]
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
s.rubyforge_project = %q{dm-sphinx-adapter}
|
19
|
-
s.rubygems_version = %q{1.3.
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
20
|
s.summary = %q{A DataMapper Sphinx adapter.}
|
21
|
-
s.test_files = ["test/test_adapter.rb", "test/
|
21
|
+
s.test_files = ["test/test_adapter.rb", "test/test_attribute.rb", "test/test_index.rb", "test/test_query.rb", "test/test_resource.rb"]
|
22
22
|
|
23
23
|
if s.respond_to? :specification_version then
|
24
24
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
@@ -26,16 +26,13 @@ Gem::Specification.new do |s|
|
|
26
26
|
|
27
27
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
28
|
s.add_runtime_dependency(%q<dm-core>, ["~> 0.9.7"])
|
29
|
-
s.add_runtime_dependency(%q<riddle>, ["~> 0.9"])
|
30
29
|
s.add_development_dependency(%q<hoe>, [">= 1.8.2"])
|
31
30
|
else
|
32
31
|
s.add_dependency(%q<dm-core>, ["~> 0.9.7"])
|
33
|
-
s.add_dependency(%q<riddle>, ["~> 0.9"])
|
34
32
|
s.add_dependency(%q<hoe>, [">= 1.8.2"])
|
35
33
|
end
|
36
34
|
else
|
37
35
|
s.add_dependency(%q<dm-core>, ["~> 0.9.7"])
|
38
|
-
s.add_dependency(%q<riddle>, ["~> 0.9"])
|
39
36
|
s.add_dependency(%q<hoe>, [">= 1.8.2"])
|
40
37
|
end
|
41
38
|
end
|
data/lib/dm-sphinx-adapter.rb
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
3
|
# TODO: Hide the shitload of dm-core warnings or at least try to?
|
4
|
-
$VERBOSE = nil
|
5
|
-
gem 'dm-core', '~> 0.9.7'
|
6
|
-
require 'dm-core'
|
4
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
5
|
+
gem 'dm-core', '~> 0.9.7'
|
6
|
+
require 'dm-core'
|
7
|
+
$VERBOSE = old_verbose
|
7
8
|
|
8
|
-
# TODO: I think I might move everything to DataMapper::Sphinx::* and ignore the default naming convention.
|
9
9
|
require 'pathname'
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
lib = Pathname(__FILE__).dirname.expand_path
|
11
|
+
dir = lib / 'dm-sphinx-adapter'
|
12
|
+
|
13
|
+
# Bundled Riddle since the gem is very old and we don't need any of the config generation stuff.
|
14
|
+
$:.unshift lib
|
15
|
+
require 'riddle'
|
16
|
+
|
17
|
+
# TODO: Require farms suck. Do something about it.
|
15
18
|
require dir / 'adapter'
|
16
|
-
require dir / 'index'
|
17
19
|
require dir / 'attribute'
|
20
|
+
require dir / 'index'
|
21
|
+
require dir / 'query'
|
18
22
|
require dir / 'resource'
|
19
|
-
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'benchmark'
|
2
|
-
|
3
1
|
module DataMapper
|
4
2
|
module Adapters
|
5
3
|
module Sphinx
|
@@ -22,48 +20,33 @@ module DataMapper
|
|
22
20
|
# - adapter Must be :sphinx
|
23
21
|
# - host Hostname (default: localhost)
|
24
22
|
# - port Optional port number (default: 3312)
|
25
|
-
# - config Optional but recommended path to sphinx config file.
|
26
23
|
#
|
27
24
|
# Alternatively supply a Hash:
|
28
25
|
# DataMapper.setup(:search, {
|
29
26
|
# :adapter => 'sphinx', # required
|
30
|
-
# :config => './sphinx.conf' # optional. Recommended though.
|
31
27
|
# :host => 'localhost', # optional. Default: localhost
|
32
28
|
# :port => 3312 # optional. Default: 3312
|
33
|
-
# :managed => true # optional. Self managed searchd server using daemon_controller.
|
34
29
|
# })
|
35
30
|
class Adapter < AbstractAdapter
|
36
31
|
|
37
32
|
# ==== See
|
38
|
-
# * DataMapper::Adapters::
|
39
|
-
# * DataMapper::Adapters::Sphinx::Client
|
33
|
+
# * DataMapper::Adapters::AbstractAdapter
|
40
34
|
#
|
41
35
|
# ==== Parameters
|
42
36
|
# uri_or_options<URI, DataObject::URI, Addressable::URI, String, Hash, Pathname>::
|
43
37
|
# DataMapper uri or options hash.
|
44
38
|
def initialize(name, uri_or_options)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
@client = managed ? ManagedClient.new(uri_or_options) : Client.new(uri_or_options)
|
39
|
+
options = normalize_options(uri_or_options)
|
40
|
+
@client = Riddle::Client.new(options.delete(:host), options.delete(:port))
|
41
|
+
options.each{|k, v| @client.method("#{k}=".to_sym).call(v) if @client.respond_to?("#{k}=".to_sym)}
|
49
42
|
end
|
50
43
|
|
51
|
-
# Interaction with searchd and indexer.
|
52
|
-
#
|
53
|
-
# ==== See
|
54
|
-
# * DataMapper::Adapters::Sphinx::Client
|
55
|
-
# * DataMapper::Adapters::Sphinx::ManagedClient
|
56
|
-
#
|
57
|
-
# ==== Returns
|
58
|
-
# DataMapper::Adapters::Sphinx::Client:: The client.
|
59
|
-
attr_reader :client
|
60
|
-
|
61
44
|
def create(resources) #:nodoc:
|
62
|
-
|
45
|
+
0
|
63
46
|
end
|
64
47
|
|
65
48
|
def delete(query) #:nodoc:
|
66
|
-
|
49
|
+
0
|
67
50
|
end
|
68
51
|
|
69
52
|
# Query your Sphinx repository and return all matching documents.
|
@@ -122,20 +105,6 @@ module DataMapper
|
|
122
105
|
indexes
|
123
106
|
end
|
124
107
|
|
125
|
-
# List sphinx delta indexes to search.
|
126
|
-
#
|
127
|
-
# ==== See
|
128
|
-
# * DataMapper::Adapters::Sphinx::Resource::ClassMethods#sphinx_indexes
|
129
|
-
#
|
130
|
-
# ==== Parameters
|
131
|
-
# model<DataMapper::Model>:: The DataMapper::Model.
|
132
|
-
#
|
133
|
-
# ==== Returns
|
134
|
-
# Array<DataMapper::Adapters::Sphinx::Index>:: Index objects from the model.
|
135
|
-
def delta_indexes(model)
|
136
|
-
indexes(model).find_all{|i| i.delta?}
|
137
|
-
end
|
138
|
-
|
139
108
|
# Query sphinx for a list of document IDs.
|
140
109
|
#
|
141
110
|
# ==== Parameters
|
@@ -147,27 +116,25 @@ module DataMapper
|
|
147
116
|
def read(query)
|
148
117
|
from = indexes(query.model).map{|index| index.name}.join(', ')
|
149
118
|
search = Sphinx::Query.new(query).to_s
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
119
|
+
|
120
|
+
client = @client.dup
|
121
|
+
client.match_mode = :extended
|
122
|
+
client.filters = search_filters(query) # By attribute.
|
123
|
+
client.limit = query.limit.to_i if query.limit
|
124
|
+
client.offset = query.offset.to_i if query.offset
|
156
125
|
|
157
126
|
if order = search_order(query)
|
158
|
-
|
159
|
-
|
160
|
-
:sort_by => order
|
161
|
-
)
|
127
|
+
client.sort_mode = :extended
|
128
|
+
client.sort_by = order
|
162
129
|
end
|
163
130
|
|
164
|
-
|
165
|
-
raise
|
131
|
+
result = client.query(search, from)
|
132
|
+
raise result[:error] unless result[:error].nil?
|
166
133
|
|
167
134
|
DataMapper.logger.info(
|
168
|
-
%q{Sphinx (%.3f): search '%s' in '%s' found %d documents} % [
|
135
|
+
%q{Sphinx (%.3f): search '%s' in '%s' found %d documents} % [result[:time], search, from, result[:total]]
|
169
136
|
)
|
170
|
-
|
137
|
+
result[:matches].map{|doc| {:id => doc[:doc]}}
|
171
138
|
end
|
172
139
|
|
173
140
|
|
@@ -177,8 +144,8 @@ module DataMapper
|
|
177
144
|
query.conditions.each do |operator, attribute, value|
|
178
145
|
next unless attribute.kind_of? Sphinx::Attribute
|
179
146
|
filters << case operator
|
180
|
-
when :eql, :like then
|
181
|
-
when :not then
|
147
|
+
when :eql, :like then attribute.filter(value)
|
148
|
+
when :not then attribute.filter(value, false)
|
182
149
|
else raise NotImplementedError.new("Sphinx: Query attributes do not support the #{operator} operator")
|
183
150
|
end
|
184
151
|
end
|
@@ -196,18 +163,25 @@ module DataMapper
|
|
196
163
|
by.empty? ? nil : by.join(', ')
|
197
164
|
end
|
198
165
|
|
199
|
-
#
|
200
|
-
#
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
166
|
+
# Coerce +uri_or_options+ into a +Hash+ of options.
|
167
|
+
#
|
168
|
+
# ==== Parameters
|
169
|
+
# uri_or_options<URI, DataObject::URI, Addressable::URI, String, Hash, Pathname>::
|
170
|
+
# DataMapper uri or options hash.
|
171
|
+
#
|
172
|
+
# ==== Returns
|
173
|
+
# Hash
|
174
|
+
def normalize_options(uri_or_options)
|
175
|
+
case uri_or_options
|
176
|
+
when String, Addressable::URI then DataObjects::URI.parse(uri_or_options).attributes
|
177
|
+
when DataObjects::URI then uri_or_options.attributes
|
178
|
+
when Pathname then {:path => uri_or_options}
|
207
179
|
else
|
208
|
-
|
180
|
+
uri_or_options[:path] ||= uri_or_options.delete(:config) || uri_or_options.delete(:database)
|
181
|
+
uri_or_options
|
209
182
|
end
|
210
183
|
end
|
184
|
+
|
211
185
|
end # Adapter
|
212
186
|
end # Sphinx
|
213
187
|
|
@@ -1,17 +1,27 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'time'
|
3
|
+
|
1
4
|
module DataMapper
|
2
5
|
module Adapters
|
3
6
|
module Sphinx
|
4
7
|
|
5
8
|
# Sphinx attribute definition.
|
6
9
|
#
|
7
|
-
#
|
10
|
+
# You must declare attributes as such if you want to use them for sorting or conditions.
|
11
|
+
#
|
12
|
+
# ==== Notes
|
13
|
+
# The following primatives will be used as sql_attr_* types. Some liberty has been taken to accommodate for as
|
14
|
+
# many DM primitives as possible.
|
8
15
|
#
|
9
16
|
# TrueClass:: sql_attr_bool
|
10
17
|
# String:: sql_attr_str2ordinal
|
18
|
+
# DataMapper::Types::Text:: sql_attr_str2ordinal
|
11
19
|
# Float:: sql_attr_float
|
12
20
|
# Integer:: sql_attr_uint
|
21
|
+
# BigDecimal:: sql_attr_float
|
13
22
|
# DateTime:: sql_attr_timestamp
|
14
23
|
# Date:: sql_attr_timestamp
|
24
|
+
# Time:: sql_attr_timestamp
|
15
25
|
# DataMapper::Types::Serial:: sql_attr_uint
|
16
26
|
class Attribute < Property
|
17
27
|
|
@@ -19,10 +29,10 @@ module DataMapper
|
|
19
29
|
TYPES = [
|
20
30
|
TrueClass, # sql_attr_bool
|
21
31
|
String, # sql_attr_str2ordinal
|
22
|
-
|
32
|
+
DataMapper::Types::Text, # sql_attr_str2ordinal
|
23
33
|
Float, # sql_attr_float
|
24
34
|
Integer, # sql_attr_uint
|
25
|
-
|
35
|
+
BigDecimal, # sql_attr_float
|
26
36
|
DateTime, # sql_attr_timestamp
|
27
37
|
Date, # sql_attr_timestamp
|
28
38
|
Time, # sql_attr_timestamp
|
@@ -32,6 +42,41 @@ module DataMapper
|
|
32
42
|
DataMapper::Types::Serial # sql_attr_uint
|
33
43
|
]
|
34
44
|
|
45
|
+
# Create a riddle client filter from a value.
|
46
|
+
#
|
47
|
+
# ==== Parameters
|
48
|
+
# value<Object>::
|
49
|
+
# The filter value to typecast and include/exclude.
|
50
|
+
#
|
51
|
+
# inclusive<Boolean>::
|
52
|
+
# Include or exclude results matching the filter value. Default: inclusive (true).
|
53
|
+
#
|
54
|
+
# ==== Returns
|
55
|
+
# Riddle::Client::Filter::
|
56
|
+
def filter(value, inclusive = true)
|
57
|
+
# Riddle uses exclusive = false as the default which doesn't read well IMO. Nobody says "Yes I don't want
|
58
|
+
# these values" you say "No I don't want these values".
|
59
|
+
value = typecast(value)
|
60
|
+
value = [value] unless value.quacks_like?([Array, Range])
|
61
|
+
Riddle::Client::Filter.new(field, value, !inclusive)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Typecasts the value into a sphinx primitive. Supports ranges or arrays of values.
|
65
|
+
#
|
66
|
+
# ==== Notes
|
67
|
+
# Some loss of precision may occur when casting BigDecimal to Float.
|
68
|
+
def typecast(value)
|
69
|
+
if value.kind_of?(Range) then Range.new(typecast(value.first), typecast(value.last))
|
70
|
+
elsif value.kind_of?(Array) then value.map{|v| typecast(v)}
|
71
|
+
elsif primitive == BigDecimal then super(value).to_f
|
72
|
+
elsif primitive == DateTime then Time.parse(super(value).to_s).to_i
|
73
|
+
elsif primitive == Date then Time.parse(super(value).to_s).to_i
|
74
|
+
elsif primitive == Time then super(value).to_i
|
75
|
+
else
|
76
|
+
super(value) # Good luck
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
35
80
|
end # Attribute
|
36
81
|
end # Sphinx
|
37
82
|
end # Adapters
|