oedipus 0.0.13 → 0.0.14
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/README.md +41 -28
- data/lib/oedipus/connection/registry.rb +56 -0
- data/lib/oedipus/connection.rb +2 -0
- data/lib/oedipus/version.rb +1 -1
- data/lib/oedipus.rb +2 -21
- data/spec/integration/connection/registry_spec.rb +59 -0
- metadata +11 -8
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# Oedipus: Sphinx 2 Search Client for Ruby
|
2
2
|
|
3
3
|
Oedipus is a client for the Sphinx search engine (>= 2.0.2), with support for
|
4
|
-
real-time indexes and multi
|
4
|
+
real-time indexes and multi-dimensional faceted searches.
|
5
5
|
|
6
6
|
It is not a clone of the PHP API, rather it is written from the ground up,
|
7
7
|
wrapping the SphinxQL API offered by searchd. Nor is it a plugin for
|
8
|
-
ActiveRecord or DataMapper... though this will
|
8
|
+
ActiveRecord or DataMapper... though this will be offered in separate gems (see
|
9
9
|
[oedipus-dm](https://github.com/d11wtq/oedipus-dm)).
|
10
10
|
|
11
11
|
Oedipus provides a level of abstraction in terms of the ease with which faceted
|
@@ -21,14 +21,17 @@ Oedipus does not (yet) provide wrappers for indexing that data via ruby [1].
|
|
21
21
|
|
22
22
|
## Dependencies
|
23
23
|
|
24
|
-
* ruby
|
25
|
-
* sphinx
|
26
|
-
* mysql
|
24
|
+
* ruby >= 1.9
|
25
|
+
* sphinx >= 2.0.2
|
26
|
+
* mysql dev libs >= 4.1
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
## Installation
|
29
|
+
|
30
|
+
Via rubygems:
|
31
|
+
|
32
|
+
```
|
33
|
+
gem install oedipus
|
34
|
+
```
|
32
35
|
|
33
36
|
## Usage
|
34
37
|
|
@@ -39,7 +42,30 @@ The following features are all currently implemented.
|
|
39
42
|
``` ruby
|
40
43
|
require "oedipus"
|
41
44
|
|
42
|
-
sphinx = Oedipus.connect('
|
45
|
+
sphinx = Oedipus.connect('127.0.0.1:9306') # sphinxql host
|
46
|
+
```
|
47
|
+
|
48
|
+
**NOTE:** Don't connect to the named host 'localhost', since the MySQL library
|
49
|
+
will try to use a UNIX socket instead of a TCP connection, which Sphinx doesn't
|
50
|
+
currently support.
|
51
|
+
|
52
|
+
Connections can be re-used by calling `Oedipus.connection` once connected.
|
53
|
+
|
54
|
+
``` ruby
|
55
|
+
sphinx = Oedipus.connection
|
56
|
+
```
|
57
|
+
|
58
|
+
If you're using Oedipus in a Rails application, you may wish to call `connect`
|
59
|
+
inside an initializer and then obtain that connection in your application, by
|
60
|
+
calling `connection`.
|
61
|
+
|
62
|
+
If you need to manage multiple connections, you may specify names for each
|
63
|
+
connection.
|
64
|
+
|
65
|
+
``` ruby
|
66
|
+
Oedipus.connect("other-host.tld:9306", :other)
|
67
|
+
|
68
|
+
sphinx = Oedipus.connection(:other)
|
43
69
|
```
|
44
70
|
|
45
71
|
### Inserting (real-time indexes)
|
@@ -76,7 +102,6 @@ sphinx[:articles].update(7, views: 103)
|
|
76
102
|
|
77
103
|
``` ruby
|
78
104
|
sphinx[:articles].delete(7)
|
79
|
-
# => true
|
80
105
|
```
|
81
106
|
|
82
107
|
### Fetching a known document (by ID)
|
@@ -90,12 +115,6 @@ record = sphinx[:articles].fetch(7)
|
|
90
115
|
|
91
116
|
You perform queries by invoking `#search` on the index.
|
92
117
|
|
93
|
-
Oedipus makes no attempt to provide an abstraction layer for the fulltext
|
94
|
-
query itself. I believe this would not be flexible enough. Sphinx fulltext
|
95
|
-
queries are extremely featureful, very dense and concise; a ruby solution
|
96
|
-
would only be lengthier and harder to understand, IMHO. Perhaps such an
|
97
|
-
abstraction could be provided by a separate gem.
|
98
|
-
|
99
118
|
|
100
119
|
``` ruby
|
101
120
|
results = sphinx[:articles].search("badgers", limit: 2)
|
@@ -231,8 +250,8 @@ attribute differently.
|
|
231
250
|
Note that Sphinx applies a limit of 20 by default, so you probably want to specify
|
232
251
|
a limit yourself. You are bound by your `max_matches` setting in sphinx.conf.
|
233
252
|
|
234
|
-
|
235
|
-
|
253
|
+
The meta data will still indicate the actual number of results that matched; you simply
|
254
|
+
get a smaller collection of materialized records.
|
236
255
|
|
237
256
|
``` ruby
|
238
257
|
sphinx[:articles].search("bobcats", limit: 50)
|
@@ -245,8 +264,8 @@ A faceted search takes a base query and a set of additional queries that are
|
|
245
264
|
variations on it. Oedipus makes this simple by allowing your facets to inherit
|
246
265
|
from the base query.
|
247
266
|
|
248
|
-
Oedipus allows you to replace '%{query}' in your facets with whatever was in
|
249
|
-
original query. This can be useful if you want to provide facets that only
|
267
|
+
Oedipus allows you to replace `'%{query}'` in your facets with whatever was in
|
268
|
+
the original query. This can be useful if you want to provide facets that only
|
250
269
|
perform the search in the title of the document (`"@title (%{query})"`) for
|
251
270
|
example.
|
252
271
|
|
@@ -380,11 +399,6 @@ To run the unit tests alone, without the need for Sphinx:
|
|
380
399
|
If you have made changes to the C extension, those changes will be compiled and installed
|
381
400
|
(to the lib/ directory) before the specs are run.
|
382
401
|
|
383
|
-
You may also compile the C extension and run the specs separately, if you prefer:
|
384
|
-
|
385
|
-
bundle exec rake compile
|
386
|
-
bundle exec rspec spec/unit/
|
387
|
-
|
388
402
|
### Footnotes
|
389
403
|
|
390
404
|
[1]: In practice I find such an abstraction not to be very useful, as it assumes a single-server setup
|
@@ -399,10 +413,9 @@ You may also compile the C extension and run the specs separately, if you prefer
|
|
399
413
|
|
400
414
|
## Future Plans
|
401
415
|
|
402
|
-
* Integration ActiveRecord
|
416
|
+
* Integration ActiveRecord
|
403
417
|
* Support for re-indexing non-realtime indexes from ruby code
|
404
418
|
* Distributed index support (sharding writes between indexes)
|
405
|
-
* Make C extension optional and provide an implementation in pure-ruby
|
406
419
|
* Query translation layer for Lucene-style AND/OR/NOT and attribute:value interpretation
|
407
420
|
* Fulltext query sanitization for unsafe user input (e.g. @@missing field)
|
408
421
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
module Oedipus
|
11
|
+
class Connection
|
12
|
+
module Registry
|
13
|
+
# Connect to Sphinx running SphinxQL.
|
14
|
+
#
|
15
|
+
# Connections are cached for re-use.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# c = Oedipus.connect("127.0.0.1:9306")
|
19
|
+
# c = Oedipus.connect(host: "127.0.0.1", port: 9306)
|
20
|
+
# c = Oedipus.connect("127.0.0.1:9306", :dist_host)
|
21
|
+
#
|
22
|
+
# @param [String|Hash] server
|
23
|
+
# a 'hostname:port' string, or
|
24
|
+
# a Hash with :host and :port keys
|
25
|
+
#
|
26
|
+
# @param [Object] key
|
27
|
+
# an optional name for the connection
|
28
|
+
#
|
29
|
+
# @return [Connection]
|
30
|
+
# a client connected to SphinxQL
|
31
|
+
def connect(options, key = :default)
|
32
|
+
connections[key] = Connection.new(options)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Lookup an already connected connection.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# c = Oedipus.connection
|
39
|
+
# c = Oedipus.connection(:dist_host)
|
40
|
+
#
|
41
|
+
# @param [Object] key
|
42
|
+
# an optional name for the connection
|
43
|
+
#
|
44
|
+
# @return [Connection]
|
45
|
+
# a client connected to SphinxQL
|
46
|
+
def connection(key = :default)
|
47
|
+
raise ArgumentError, "Connection #{key} is not defined" unless connections.key?(key)
|
48
|
+
connections[key]
|
49
|
+
end
|
50
|
+
|
51
|
+
def connections
|
52
|
+
@connections ||= {}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/oedipus/connection.rb
CHANGED
data/lib/oedipus/version.rb
CHANGED
data/lib/oedipus.rb
CHANGED
@@ -30,30 +30,11 @@ require "oedipus/query_builder"
|
|
30
30
|
require "oedipus/connection_error"
|
31
31
|
require "oedipus/connection"
|
32
32
|
require "oedipus/connection/pool"
|
33
|
+
require "oedipus/connection/registry"
|
33
34
|
|
34
35
|
require "oedipus/index"
|
35
36
|
|
36
37
|
module Oedipus
|
37
38
|
extend Comparison::Shortcuts
|
38
|
-
|
39
|
-
class << self
|
40
|
-
# Connect to Sphinx running SphinxQL.
|
41
|
-
#
|
42
|
-
# @example
|
43
|
-
# c = Oedipus.connect("localhost:9306")
|
44
|
-
# c = Oedipus.connect(host: "localhost", port: 9306)
|
45
|
-
#
|
46
|
-
# @param [String] server
|
47
|
-
# a 'hostname:port' string
|
48
|
-
#
|
49
|
-
# @param [Hash] options
|
50
|
-
# a Hash with :host and :port keys
|
51
|
-
#
|
52
|
-
# @return [Connection]
|
53
|
-
# a client connected to SphinxQL
|
54
|
-
def connect(options)
|
55
|
-
# TODO: Add pooling
|
56
|
-
Connection.new(options)
|
57
|
-
end
|
58
|
-
end
|
39
|
+
extend Connection::Registry
|
59
40
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
require "oedipus/rspec/test_harness"
|
12
|
+
|
13
|
+
describe Oedipus::Connection::Registry do
|
14
|
+
include Oedipus::RSpec::TestHarness
|
15
|
+
|
16
|
+
before(:all) do
|
17
|
+
set_data_dir File.expand_path("../../../data", __FILE__)
|
18
|
+
set_searchd ENV["SEARCHD"]
|
19
|
+
start_searchd
|
20
|
+
end
|
21
|
+
|
22
|
+
after(:all) { stop_searchd }
|
23
|
+
|
24
|
+
before(:each) { empty_indexes }
|
25
|
+
|
26
|
+
let(:registry) do
|
27
|
+
Object.new.tap { |o| o.send(:extend, Oedipus::Connection::Registry) }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#connect" do
|
31
|
+
it "makes a new connection to a SphinxQL host" do
|
32
|
+
registry.connect(searchd_host).should be_a_kind_of(Oedipus::Connection)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#connection" do
|
37
|
+
context "without a name" do
|
38
|
+
let(:conn) { registry.connect(searchd_host) }
|
39
|
+
|
40
|
+
it "returns an existing connection" do
|
41
|
+
conn.should equal registry.connection
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "with a name" do
|
46
|
+
let(:conn) { registry.connect(searchd_host, :bob) }
|
47
|
+
|
48
|
+
it "returns the named connection" do
|
49
|
+
conn.should equal registry.connection(:bob)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with a bad name" do
|
54
|
+
it "raises an ArgumentError" do
|
55
|
+
expect { registry.connection(:wrong) }.to raise_error(ArgumentError)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oedipus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &12537160 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *12537160
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake-compiler
|
27
|
-
requirement: &
|
27
|
+
requirement: &12535680 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *12535680
|
36
36
|
description: ! "== Sphinx 2 Comes to Ruby\n\nOedipus brings full support for Sphinx
|
37
37
|
2 to Ruby:\n\n - real-time indexes (insert, replace, update, delete)\n - faceted
|
38
38
|
search (variations on a base query)\n - multi-queries (multiple queries executed
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- lib/oedipus/comparison/shortcuts.rb
|
74
74
|
- lib/oedipus/connection.rb
|
75
75
|
- lib/oedipus/connection/pool.rb
|
76
|
+
- lib/oedipus/connection/registry.rb
|
76
77
|
- lib/oedipus/connection_error.rb
|
77
78
|
- lib/oedipus/index.rb
|
78
79
|
- lib/oedipus/query_builder.rb
|
@@ -80,6 +81,7 @@ files:
|
|
80
81
|
- lib/oedipus/version.rb
|
81
82
|
- oedipus.gemspec
|
82
83
|
- spec/data/.gitkeep
|
84
|
+
- spec/integration/connection/registry_spec.rb
|
83
85
|
- spec/integration/connection_spec.rb
|
84
86
|
- spec/integration/index_spec.rb
|
85
87
|
- spec/spec_helper.rb
|
@@ -111,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
113
|
version: '0'
|
112
114
|
segments:
|
113
115
|
- 0
|
114
|
-
hash:
|
116
|
+
hash: -1945313164651030981
|
115
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
118
|
none: false
|
117
119
|
requirements:
|
@@ -120,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
122
|
version: '0'
|
121
123
|
segments:
|
122
124
|
- 0
|
123
|
-
hash:
|
125
|
+
hash: -1945313164651030981
|
124
126
|
requirements: []
|
125
127
|
rubyforge_project: oedipus
|
126
128
|
rubygems_version: 1.8.11
|
@@ -129,6 +131,7 @@ specification_version: 3
|
|
129
131
|
summary: Sphinx 2 Search Client for Ruby
|
130
132
|
test_files:
|
131
133
|
- spec/data/.gitkeep
|
134
|
+
- spec/integration/connection/registry_spec.rb
|
132
135
|
- spec/integration/connection_spec.rb
|
133
136
|
- spec/integration/index_spec.rb
|
134
137
|
- spec/spec_helper.rb
|