xapian_db 0.3.1 → 0.3.2
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/CHANGELOG.md +33 -0
- data/LICENSE +20 -0
- data/README.rdoc +168 -0
- data/lib/xapian_db/adapters/active_record_adapter.rb +30 -30
- data/lib/xapian_db/adapters/datamapper_adapter.rb +29 -18
- data/lib/xapian_db/adapters/generic_adapter.rb +21 -12
- data/lib/xapian_db/config.rb +63 -30
- data/lib/xapian_db/database.rb +61 -28
- data/lib/xapian_db/document_blueprint.rb +90 -38
- data/lib/xapian_db/index_writers/direct_writer.rb +26 -14
- data/lib/xapian_db/indexer.rb +51 -20
- data/lib/xapian_db/query_parser.rb +17 -14
- data/lib/xapian_db/railtie.rb +8 -7
- data/lib/xapian_db/resultset.rb +33 -22
- data/lib/xapian_db.rb +35 -16
- metadata +38 -21
- data/CHANGELOG +0 -15
- data/examples/basic.rb +0 -59
data/lib/xapian_db/resultset.rb
CHANGED
@@ -1,51 +1,62 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
# The resultset holds a Xapian::Query object and allows paged access
|
4
|
-
# to the found documents.
|
5
|
-
# author Gernot Kogler
|
6
|
-
|
7
3
|
module XapianDb
|
8
|
-
|
4
|
+
|
5
|
+
# The resultset encapsulates a Xapian::Query object and allows paged access
|
6
|
+
# to the found documents.
|
7
|
+
# @example Process the first page of a resultsest
|
8
|
+
# resultset.paginate(:page => 1, :per_page => 10).each do |doc|
|
9
|
+
# # do something with the xapian document
|
10
|
+
# end
|
11
|
+
# @author Gernot Kogler
|
9
12
|
class Resultset
|
10
|
-
|
13
|
+
|
14
|
+
# The number of documents found
|
15
|
+
# @return [Integer]
|
11
16
|
attr_reader :size
|
12
|
-
|
17
|
+
|
13
18
|
# Constructor
|
14
|
-
# @param [Xapian::Enquire] a Xapian query result
|
15
|
-
|
19
|
+
# @param [Xapian::Enquire] enquiry a Xapian query result (see http://xapian.org/docs/apidoc/html/classXapian_1_1Enquire.html)
|
20
|
+
# @param [Hash] options
|
21
|
+
# @option options [Integer] :per_page (10) How many docs per page?
|
22
|
+
def initialize(enquiry, options)
|
16
23
|
@enquiry = enquiry
|
17
24
|
# By passing 0 as the max parameter to the mset method,
|
18
25
|
# we only get statistics about the query, no results
|
19
|
-
@size
|
26
|
+
@size = enquiry.mset(0, 0).matches_estimated
|
27
|
+
@per_page = options[:per_page]
|
20
28
|
end
|
21
29
|
|
22
30
|
# Paginate the result
|
31
|
+
# @param [Hash] opts Options for the persistent database
|
32
|
+
# @option opts [Integer] :page (1) The page to access
|
23
33
|
def paginate(opts={})
|
24
|
-
options = {:page => 1
|
25
|
-
|
26
|
-
return [] if offset > @size
|
27
|
-
build_page(offset, options[:per_page])
|
34
|
+
options = {:page => 1}.merge(opts)
|
35
|
+
build_page(options[:page])
|
28
36
|
end
|
29
|
-
|
37
|
+
|
30
38
|
private
|
31
|
-
|
39
|
+
|
32
40
|
# Build a page of Xapian documents
|
33
|
-
|
41
|
+
# @return [Array<Xapian::Document>] An array of xapian documents
|
42
|
+
def build_page(page)
|
34
43
|
docs = []
|
35
|
-
|
44
|
+
offset = (page - 1) * @per_page
|
45
|
+
return [] if offset > @size
|
46
|
+
result_window = @enquiry.mset(offset, @per_page)
|
36
47
|
result_window.matches.each do |match|
|
37
48
|
docs << decorate(match.document)
|
38
49
|
end
|
39
50
|
docs
|
40
51
|
end
|
41
|
-
|
42
|
-
# Decorate a Xapian document with field accessors
|
52
|
+
|
53
|
+
# Decorate a Xapian document with field accessors for each configured attribute
|
43
54
|
def decorate(document)
|
44
55
|
klass_name = document.values[0].value
|
45
56
|
blueprint = XapianDb::DocumentBlueprint.blueprint_for(Kernel.const_get(klass_name))
|
46
57
|
document.extend blueprint.accessors_module
|
47
58
|
end
|
48
|
-
|
59
|
+
|
49
60
|
end
|
50
|
-
|
61
|
+
|
51
62
|
end
|
data/lib/xapian_db.rb
CHANGED
@@ -1,45 +1,64 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'digest/sha1'
|
2
|
-
require 'rubygems'
|
3
4
|
require 'xapian'
|
4
5
|
require 'yaml'
|
5
|
-
|
6
|
+
|
7
|
+
# This is the top level module of xapian_db. It allows you to
|
8
|
+
# configure XapianDB, create / open databases and perform
|
9
|
+
# searches.
|
10
|
+
|
11
|
+
# @author Gernot Kogler
|
6
12
|
|
7
13
|
module XapianDb
|
8
14
|
|
9
|
-
#
|
15
|
+
# Global configuration for XapianDb. See {XapianDb::Config.setup}
|
16
|
+
# for available options
|
10
17
|
def self.setup(&block)
|
11
18
|
XapianDb::Config.setup(&block)
|
12
19
|
end
|
13
|
-
|
14
|
-
# Create a database
|
15
|
-
#
|
20
|
+
|
21
|
+
# Create a database
|
22
|
+
# @param [Hash] options
|
23
|
+
# @option options [String] :path A path to the file system. If no path is
|
24
|
+
# given, creates an in memory database. <b>Overwrites an existing database!</b>
|
25
|
+
# @return [XapianDb::Database]
|
16
26
|
def self.create_db(options = {})
|
17
|
-
if options[:path]
|
18
|
-
PersistentDatabase.new(:path => options[:path], :create => true)
|
27
|
+
if options[:path]
|
28
|
+
PersistentDatabase.new(:path => options[:path], :create => true)
|
19
29
|
else
|
20
30
|
InMemoryDatabase.new
|
21
31
|
end
|
22
32
|
end
|
23
33
|
|
24
|
-
# Open a database
|
34
|
+
# Open a database
|
35
|
+
# @param [Hash] options
|
36
|
+
# @option options [String] :path A path to the file system. If no path is
|
37
|
+
# given, creates an in memory database. If a path is given, then database
|
38
|
+
# must exist.
|
39
|
+
# @return [XapianDb::Database]
|
25
40
|
def self.open_db(options = {})
|
26
|
-
if options[:path]
|
27
|
-
PersistentDatabase.new(:path => options[:path], :create => false)
|
41
|
+
if options[:path]
|
42
|
+
PersistentDatabase.new(:path => options[:path], :create => false)
|
28
43
|
else
|
29
44
|
InMemoryDatabase.new
|
30
45
|
end
|
31
46
|
end
|
32
|
-
|
33
|
-
# Access
|
47
|
+
|
48
|
+
# Access the configured database. See {XapianDb::Config.setup}
|
49
|
+
# for instructions on how to configure a database
|
50
|
+
# @return [XapianDb::Database]
|
34
51
|
def self.database
|
35
52
|
XapianDb::Config.database
|
36
53
|
end
|
37
|
-
|
38
|
-
# Query the database
|
54
|
+
|
55
|
+
# Query the configured database.
|
56
|
+
# See {XapianDb::Database#search} for options
|
57
|
+
# @return [XapianDb::Resultset]
|
39
58
|
def self.search(expression)
|
40
59
|
XapianDb::Config.database.search(expression)
|
41
60
|
end
|
42
|
-
|
61
|
+
|
43
62
|
end
|
44
63
|
|
45
64
|
require File.dirname(__FILE__) + '/xapian_db/config'
|
metadata
CHANGED
@@ -5,20 +5,20 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 2
|
9
|
+
version: 0.3.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
|
-
- Gernot
|
12
|
+
- Gernot Kogler
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-12-
|
17
|
+
date: 2010-12-10 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: rspec
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
@@ -26,35 +26,51 @@ dependencies:
|
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
segments:
|
29
|
+
- 2
|
30
|
+
- 1
|
29
31
|
- 0
|
30
|
-
|
31
|
-
|
32
|
-
version: 0.9.0
|
33
|
-
type: :runtime
|
32
|
+
version: 2.1.0
|
33
|
+
type: :development
|
34
34
|
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: simplecov
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 3
|
46
|
+
- 2
|
47
|
+
version: 0.3.2
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
35
50
|
description: Ruby library to use a Xapian db as a key/value store with high performance fulltext search
|
36
51
|
email: gernot.kogler (at) garaio (dot) com
|
37
52
|
executables: []
|
38
53
|
|
39
54
|
extensions: []
|
40
55
|
|
41
|
-
extra_rdoc_files:
|
42
|
-
|
56
|
+
extra_rdoc_files: []
|
57
|
+
|
43
58
|
files:
|
44
|
-
-
|
45
|
-
- lib/xapian_db.rb
|
46
|
-
- lib/xapian_db/
|
59
|
+
- lib/xapian_db/adapters/active_record_adapter.rb
|
60
|
+
- lib/xapian_db/adapters/datamapper_adapter.rb
|
61
|
+
- lib/xapian_db/adapters/generic_adapter.rb
|
47
62
|
- lib/xapian_db/config.rb
|
48
|
-
- lib/xapian_db/index_writers/direct_writer.rb
|
49
63
|
- lib/xapian_db/database.rb
|
50
64
|
- lib/xapian_db/document_blueprint.rb
|
65
|
+
- lib/xapian_db/index_writers/direct_writer.rb
|
51
66
|
- lib/xapian_db/indexer.rb
|
52
|
-
- lib/xapian_db/adapters/generic_adapter.rb
|
53
|
-
- lib/xapian_db/adapters/datamapper_adapter.rb
|
54
|
-
- lib/xapian_db/adapters/active_record_adapter.rb
|
55
67
|
- lib/xapian_db/query_parser.rb
|
68
|
+
- lib/xapian_db/railtie.rb
|
56
69
|
- lib/xapian_db/resultset.rb
|
57
|
-
-
|
70
|
+
- lib/xapian_db.rb
|
71
|
+
- LICENSE
|
72
|
+
- README.rdoc
|
73
|
+
- CHANGELOG.md
|
58
74
|
has_rdoc: true
|
59
75
|
homepage: https://github.com/garaio/xapian_db
|
60
76
|
licenses: []
|
@@ -84,8 +100,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
100
|
- !ruby/object:Gem::Version
|
85
101
|
segments:
|
86
102
|
- 1
|
87
|
-
-
|
88
|
-
|
103
|
+
- 3
|
104
|
+
- 6
|
105
|
+
version: 1.3.6
|
89
106
|
requirements: []
|
90
107
|
|
91
108
|
rubyforge_project:
|
data/CHANGELOG
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
*0.1.0* (November 23th, 2010)
|
2
|
-
|
3
|
-
* Proof of concept, not really useful for real world usage
|
4
|
-
|
5
|
-
*0.2.0* (December 1st, 2010)
|
6
|
-
|
7
|
-
* Blueprint configuration extended
|
8
|
-
* Adapter for Datamapper
|
9
|
-
* Search by attribute names
|
10
|
-
* Search with wildcards
|
11
|
-
* Document attributes can carry anything that is serializable by YAML
|
12
|
-
|
13
|
-
*0.3.0* (December 4st, 2010)
|
14
|
-
|
15
|
-
* Rails integration with configuration file (config/xapian_db.yml) and automatic setup
|
data/examples/basic.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# This example shows the most basic way to use xapian_db
|
4
|
-
# To run the example, please install the xapian_db gem first
|
5
|
-
|
6
|
-
require 'rubygems'
|
7
|
-
require 'xapian_db'
|
8
|
-
|
9
|
-
puts "Setting up the demo..."
|
10
|
-
|
11
|
-
# 1: Open an in memory database
|
12
|
-
db = XapianDb.create_db
|
13
|
-
|
14
|
-
# 2: Define a class which should get indexed; we define a class that
|
15
|
-
# could be an ActiveRecord or Datamapper Domain class
|
16
|
-
class People
|
17
|
-
|
18
|
-
attr_accessor :id, :name, :first_name
|
19
|
-
|
20
|
-
def initialize(data)
|
21
|
-
@id, @name, @first_name = data[:id], data[:name], data[:first_name]
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
# 3: Configure the generic adapter with a unique key expression
|
27
|
-
XapianDb::Adapters::GenericAdapter.unique_key do
|
28
|
-
"#{self.class}-#{self.id}"
|
29
|
-
end
|
30
|
-
|
31
|
-
# 4: Define a document blueprint for our class; the blueprint describes
|
32
|
-
# the structure of all documents for our class. Attribute values can
|
33
|
-
# be accessed later for each retrieved doc. Attributes are indexed
|
34
|
-
# by default.
|
35
|
-
XapianDb::DocumentBlueprint.setup(People) do |blueprint|
|
36
|
-
blueprint.attribute :name
|
37
|
-
blueprint.attribute :first_name
|
38
|
-
end
|
39
|
-
|
40
|
-
# 5: Let's create some objects
|
41
|
-
person_1 = People.new(:id => 1, :name => "Kogler", :first_name => "Gernot")
|
42
|
-
person_2 = People.new(:id => 2, :name => "Frey", :first_name => "Daniel")
|
43
|
-
person_3 = People.new(:id => 3, :name => "Garaio", :first_name => "Thomas")
|
44
|
-
|
45
|
-
# 6: Now add them to the database
|
46
|
-
blueprint = XapianDb::DocumentBlueprint.blueprint_for(People)
|
47
|
-
db.store_doc(blueprint.indexer.build_document_for(person_1))
|
48
|
-
db.store_doc(blueprint.indexer.build_document_for(person_2))
|
49
|
-
db.store_doc(blueprint.indexer.build_document_for(person_3))
|
50
|
-
|
51
|
-
# 7: Now find the gem author ;-)
|
52
|
-
puts "Searching for Gernot..."
|
53
|
-
results = db.search("Gernot")
|
54
|
-
puts "We found #{results.size} documents"
|
55
|
-
puts "And the first document looks like this:"
|
56
|
-
page = results.paginate(:page => 1)
|
57
|
-
doc = page.first
|
58
|
-
puts "name: #{doc.name}"
|
59
|
-
puts "first name: #{doc.first_name}"
|