xapian_db 0.5.7 → 0.5.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +10 -0
- data/README.rdoc +18 -0
- data/lib/xapian_db/adapters/active_record_adapter.rb +6 -6
- data/lib/xapian_db/adapters/datamapper_adapter.rb +4 -4
- data/lib/xapian_db/config.rb +5 -11
- data/lib/xapian_db/document_blueprint.rb +2 -7
- data/lib/xapian_db/index_writers/transactional_writer.rb +51 -0
- data/lib/xapian_db/railtie.rb +3 -4
- data/lib/xapian_db/utilities.rb +16 -0
- data/lib/xapian_db.rb +44 -2
- metadata +28 -4
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
##0.5.8 (March 22th, 2011)
|
2
|
+
|
3
|
+
Fixes:
|
4
|
+
|
5
|
+
- automatic reindexing of a changed object now works when using beanstalk and the worker rake task
|
6
|
+
|
7
|
+
Features:
|
8
|
+
|
9
|
+
- support for transactions (see the README for details)
|
10
|
+
|
1
11
|
##0.5.7 (March 7th, 2011)
|
2
12
|
|
3
13
|
Fixes:
|
data/README.rdoc
CHANGED
@@ -116,6 +116,14 @@ You may add a filter expression to exclude objects from the index. This is handy
|
|
116
116
|
blueprint.ignore_if {active == false}
|
117
117
|
end
|
118
118
|
|
119
|
+
You can override the global adapter configuration in a specific blueprint. Let's say you use ActiveRecord, but you have
|
120
|
+
one more class that is not stored in the database, but you want it to be indexed:
|
121
|
+
|
122
|
+
XapianDb::DocumentBlueprint.setup(SpecialClass) do |blueprint|
|
123
|
+
blueprint.adapter :generic
|
124
|
+
blueprint.index :some_stuff
|
125
|
+
end
|
126
|
+
|
119
127
|
place these configurations either into the corresponding class or - I prefer to have the index configurations outside
|
120
128
|
the models - into the file config/xapian_blueprints.rb.
|
121
129
|
|
@@ -226,6 +234,16 @@ A global facet search always groups the results by the class of the indexed obje
|
|
226
234
|
|
227
235
|
At the class level, any attribute can be used for a facet query.
|
228
236
|
|
237
|
+
=== Transactions
|
238
|
+
|
239
|
+
You can execute a block of code inside a XapianDb transaction. This ensures that the changed objects in your block will get reindexed
|
240
|
+
only if the block does not raise an exception.
|
241
|
+
|
242
|
+
XapianDb.transaction do
|
243
|
+
object1.save
|
244
|
+
object2.save
|
245
|
+
end
|
246
|
+
|
229
247
|
== Production setup
|
230
248
|
|
231
249
|
Since Xapian allows only one database instance to write to the index, the default setup of XapianDb will not work
|
@@ -10,7 +10,7 @@ module XapianDb
|
|
10
10
|
# This adapter does the following:
|
11
11
|
# - adds the instance method <code>xapian_id</code> to an indexed class
|
12
12
|
# - adds the class method <code>rebuild_xapian_index</code> to an indexed class
|
13
|
-
# - adds an after
|
13
|
+
# - adds an after commit block to an indexed class to update the index
|
14
14
|
# - adds an after destroy block to an indexed class to update the index
|
15
15
|
# - adds the instance method <code>indexed_object</code> to the module that will be included
|
16
16
|
# in every found xapian document
|
@@ -38,24 +38,24 @@ module XapianDb
|
|
38
38
|
klass.class_eval do
|
39
39
|
|
40
40
|
# add the after save logic
|
41
|
-
|
41
|
+
after_commit do
|
42
42
|
blueprint = XapianDb::DocumentBlueprint.blueprint_for klass
|
43
43
|
if blueprint.should_index?(self)
|
44
|
-
XapianDb
|
44
|
+
XapianDb.index(self)
|
45
45
|
else
|
46
|
-
XapianDb
|
46
|
+
XapianDb.unindex(self)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
# add the after destroy logic
|
51
51
|
after_destroy do
|
52
|
-
XapianDb
|
52
|
+
XapianDb.unindex(self)
|
53
53
|
end
|
54
54
|
|
55
55
|
# Add a method to reindex all models of this class
|
56
56
|
define_singleton_method(:rebuild_xapian_index) do |options={}|
|
57
57
|
options[:primary_key] = klass.primary_key
|
58
|
-
XapianDb
|
58
|
+
XapianDb.reindex_class(klass, options)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -40,21 +40,21 @@ module XapianDb
|
|
40
40
|
after :save do
|
41
41
|
blueprint = XapianDb::DocumentBlueprint.blueprint_for klass
|
42
42
|
if blueprint.should_index?(self)
|
43
|
-
XapianDb
|
43
|
+
XapianDb.index(self)
|
44
44
|
else
|
45
|
-
XapianDb
|
45
|
+
XapianDb.unindex(self)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
# add the after destroy logic
|
50
50
|
after :destroy do
|
51
|
-
XapianDb
|
51
|
+
XapianDb.unindex(self)
|
52
52
|
end
|
53
53
|
|
54
54
|
# Add a method to reindex all models of this class
|
55
55
|
define_singleton_method(:rebuild_xapian_index) do |options={}|
|
56
56
|
options[:primary_key] = klass.serial.name
|
57
|
-
XapianDb
|
57
|
+
XapianDb.reindex_class(self, options)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
data/lib/xapian_db/config.rb
CHANGED
@@ -12,6 +12,8 @@ module XapianDb
|
|
12
12
|
# @author Gernot Kogler
|
13
13
|
class Config
|
14
14
|
|
15
|
+
include XapianDb::Utilities
|
16
|
+
|
15
17
|
# ---------------------------------------------------------------------------------
|
16
18
|
# Singleton methods
|
17
19
|
# ---------------------------------------------------------------------------------
|
@@ -48,7 +50,6 @@ module XapianDb
|
|
48
50
|
# DSL methods
|
49
51
|
# ---------------------------------------------------------------------------------
|
50
52
|
|
51
|
-
#
|
52
53
|
attr_reader :_database, :_adapter, :_writer, :_beanstalk_daemon, :_stemmer, :_stopper
|
53
54
|
|
54
55
|
# Set the global database to use
|
@@ -108,16 +109,9 @@ module XapianDb
|
|
108
109
|
# end
|
109
110
|
# see {LANGUAGE_MAP} for supported languages
|
110
111
|
def language(lang)
|
111
|
-
|
112
|
-
@_stemmer = XapianDb::Repositories::Stemmer.stemmer_for
|
113
|
-
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
# TODO: move this to a helper module
|
119
|
-
def camelize(string)
|
120
|
-
string.split(/[^a-z0-9]/i).map{|w| w.capitalize}.join
|
112
|
+
lang ||= :none
|
113
|
+
@_stemmer = XapianDb::Repositories::Stemmer.stemmer_for lang
|
114
|
+
@_stopper = lang == :none ? nil : XapianDb::Repositories::Stopper.stopper_for(lang)
|
121
115
|
end
|
122
116
|
|
123
117
|
end
|
@@ -19,6 +19,8 @@ module XapianDb
|
|
19
19
|
# @author Gernot Kogler
|
20
20
|
class DocumentBlueprint
|
21
21
|
|
22
|
+
include XapianDb::Utilities
|
23
|
+
|
22
24
|
# ---------------------------------------------------------------------------------
|
23
25
|
# Singleton methods
|
24
26
|
# ---------------------------------------------------------------------------------
|
@@ -295,13 +297,6 @@ module XapianDb
|
|
295
297
|
@reserved_method_names.include?(attr_name.to_sym)
|
296
298
|
end
|
297
299
|
|
298
|
-
private
|
299
|
-
|
300
|
-
# TODO: move this to a helper module
|
301
|
-
def camelize(string)
|
302
|
-
string.split(/[^a-z0-9]/i).map{|w| w.capitalize}.join
|
303
|
-
end
|
304
|
-
|
305
300
|
end
|
306
301
|
|
307
302
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# This writer collects index change requests but does not submit them immediately to the database.
|
4
|
+
# The index changes are applied when the commit method is called.
|
5
|
+
# This writer is intended for internal use only. Do not use it in a xapian configuration!
|
6
|
+
# @author Gernot Kogler
|
7
|
+
|
8
|
+
module XapianDb
|
9
|
+
module IndexWriters
|
10
|
+
|
11
|
+
class TransactionalWriter
|
12
|
+
|
13
|
+
attr_reader :index_requests, :unindex_requests
|
14
|
+
|
15
|
+
# Constructor
|
16
|
+
def initialize
|
17
|
+
@index_requests = []
|
18
|
+
@unindex_requests = []
|
19
|
+
end
|
20
|
+
|
21
|
+
# Update an object in the index
|
22
|
+
# @param [Object] obj An instance of a class with a blueprint configuration
|
23
|
+
def index(obj)
|
24
|
+
@index_requests << obj
|
25
|
+
end
|
26
|
+
|
27
|
+
# Remove an object from the index
|
28
|
+
# @param [Object] obj An instance of a class with a blueprint configuration
|
29
|
+
def unindex(obj)
|
30
|
+
@unindex_requests << obj
|
31
|
+
end
|
32
|
+
|
33
|
+
# Reindex all objects of a given class
|
34
|
+
# @param [Class] klass The class to reindex
|
35
|
+
# @param [Hash] options Options for reindexing
|
36
|
+
# @option options [Boolean] :verbose (false) Should the reindexing give status informations?
|
37
|
+
def reindex_class(klass, options={})
|
38
|
+
raise "rebuild_xapian_index is not supported in transactions"
|
39
|
+
end
|
40
|
+
|
41
|
+
# Commit all pending changes to the database
|
42
|
+
# @param [DirectWriter, BeanstalkWriter] writer The writer to use
|
43
|
+
def commit_using(writer)
|
44
|
+
@index_requests.each { |obj| writer.index obj }
|
45
|
+
@unindex_requests.each { |obj| writer.unindex obj }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
data/lib/xapian_db/railtie.rb
CHANGED
@@ -34,10 +34,10 @@ module XapianDb
|
|
34
34
|
else
|
35
35
|
config.database File.expand_path @database_path
|
36
36
|
end
|
37
|
-
config.adapter @adapter.to_sym
|
38
|
-
config.writer @writer.to_sym
|
37
|
+
config.adapter @adapter.try(:to_sym)
|
38
|
+
config.writer @writer.try(:to_sym)
|
39
39
|
config.beanstalk_daemon_url @beanstalk_daemon
|
40
|
-
config.language @language
|
40
|
+
config.language @language.try(:to_sym)
|
41
41
|
end
|
42
42
|
|
43
43
|
end
|
@@ -66,7 +66,6 @@ module XapianDb
|
|
66
66
|
@adapter = :active_record
|
67
67
|
@writer = :direct
|
68
68
|
@beanstalk_daemon = nil
|
69
|
-
@language = :en
|
70
69
|
end
|
71
70
|
|
72
71
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Collection of utility methods
|
4
|
+
# @author Gernot Kogler
|
5
|
+
module XapianDb
|
6
|
+
module Utilities
|
7
|
+
|
8
|
+
# Convert a string to camel case
|
9
|
+
# @param [String] The string to camelize
|
10
|
+
# @return [String] The camelized string
|
11
|
+
def camelize(string)
|
12
|
+
string.split(/[^a-z0-9]/i).map{|w| w.capitalize}.join
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/lib/xapian_db.rb
CHANGED
@@ -34,6 +34,7 @@ module XapianDb
|
|
34
34
|
# for available options
|
35
35
|
def self.setup(&block)
|
36
36
|
XapianDb::Config.setup(&block)
|
37
|
+
@writer = XapianDb::Config.writer
|
37
38
|
end
|
38
39
|
|
39
40
|
# Create a database
|
@@ -84,6 +85,26 @@ module XapianDb
|
|
84
85
|
XapianDb::Config.database.facets(expression)
|
85
86
|
end
|
86
87
|
|
88
|
+
# Update an object in the index
|
89
|
+
# @param [Object] obj An instance of a class with a blueprint configuration
|
90
|
+
def self.index(obj)
|
91
|
+
@writer.index obj
|
92
|
+
end
|
93
|
+
|
94
|
+
# Remove an object from the index
|
95
|
+
# @param [Object] obj An instance of a class with a blueprint configuration
|
96
|
+
def self.unindex(obj)
|
97
|
+
@writer.unindex obj
|
98
|
+
end
|
99
|
+
|
100
|
+
# Reindex all objects of a given class
|
101
|
+
# @param [Class] klass The class to reindex
|
102
|
+
# @param [Hash] options Options for reindexing
|
103
|
+
# @option options [Boolean] :verbose (false) Should the reindexing give status informations?
|
104
|
+
def self.reindex_class(klass, options={})
|
105
|
+
@writer.reindex_class klass, options
|
106
|
+
end
|
107
|
+
|
87
108
|
# Rebuild the xapian index for all configured blueprints
|
88
109
|
# @param [Hash] options Options for reindexing
|
89
110
|
# @option options [Boolean] :verbose (false) Should the reindexing give status informations?
|
@@ -97,11 +118,32 @@ module XapianDb
|
|
97
118
|
true
|
98
119
|
end
|
99
120
|
|
121
|
+
# Execute a block as a transaction
|
122
|
+
def self.transaction(&block)
|
123
|
+
# Temporarily use the transactional writer
|
124
|
+
@writer = XapianDb::IndexWriters::TransactionalWriter.new
|
125
|
+
begin
|
126
|
+
block.call
|
127
|
+
@writer.commit_using XapianDb::Config.writer
|
128
|
+
rescue Exception => ex
|
129
|
+
msg = "error in XapianDb transaction block: #{ex}, transaction aborted"
|
130
|
+
if defined?(Rails)
|
131
|
+
Rails.logger.error msg
|
132
|
+
else
|
133
|
+
puts msg
|
134
|
+
end
|
135
|
+
ensure
|
136
|
+
# switch back to the configured writer
|
137
|
+
@writer = XapianDb::Config.writer
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
100
141
|
end
|
101
142
|
|
102
|
-
do_not_require = %w(update_stopwords.rb railtie.rb base_adapter.rb beanstalk_writer.rb)
|
143
|
+
do_not_require = %w(update_stopwords.rb railtie.rb base_adapter.rb beanstalk_writer.rb utilities.rb)
|
103
144
|
files = Dir.glob("#{File.dirname(__FILE__)}/**/*.rb").reject{|path| do_not_require.include?(File.basename(path))}
|
104
|
-
# Require
|
145
|
+
# Require these first
|
146
|
+
require "#{File.dirname(__FILE__)}/xapian_db/utilities"
|
105
147
|
require "#{File.dirname(__FILE__)}/xapian_db/adapters/base_adapter"
|
106
148
|
files.each {|file| require file}
|
107
149
|
|
metadata
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xapian_db
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 5
|
8
|
+
- 8
|
9
|
+
version: 0.5.8
|
6
10
|
platform: ruby
|
7
11
|
authors:
|
8
12
|
- Gernot Kogler
|
@@ -10,7 +14,7 @@ autorequire:
|
|
10
14
|
bindir: bin
|
11
15
|
cert_chain: []
|
12
16
|
|
13
|
-
date: 2011-03-
|
17
|
+
date: 2011-03-23 00:00:00 +01:00
|
14
18
|
default_executable:
|
15
19
|
dependencies:
|
16
20
|
- !ruby/object:Gem::Dependency
|
@@ -21,6 +25,10 @@ dependencies:
|
|
21
25
|
requirements:
|
22
26
|
- - ">="
|
23
27
|
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 2
|
30
|
+
- 3
|
31
|
+
- 1
|
24
32
|
version: 2.3.1
|
25
33
|
type: :development
|
26
34
|
version_requirements: *id001
|
@@ -32,6 +40,10 @@ dependencies:
|
|
32
40
|
requirements:
|
33
41
|
- - ">="
|
34
42
|
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 3
|
46
|
+
- 7
|
35
47
|
version: 0.3.7
|
36
48
|
type: :development
|
37
49
|
version_requirements: *id002
|
@@ -43,6 +55,10 @@ dependencies:
|
|
43
55
|
requirements:
|
44
56
|
- - ">="
|
45
57
|
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 1
|
60
|
+
- 1
|
61
|
+
- 0
|
46
62
|
version: 1.1.0
|
47
63
|
type: :development
|
48
64
|
version_requirements: *id003
|
@@ -65,6 +81,7 @@ files:
|
|
65
81
|
- lib/xapian_db/index_writers/beanstalk_worker.rb
|
66
82
|
- lib/xapian_db/index_writers/beanstalk_writer.rb
|
67
83
|
- lib/xapian_db/index_writers/direct_writer.rb
|
84
|
+
- lib/xapian_db/index_writers/transactional_writer.rb
|
68
85
|
- lib/xapian_db/indexer.rb
|
69
86
|
- lib/xapian_db/query_parser.rb
|
70
87
|
- lib/xapian_db/railtie.rb
|
@@ -86,6 +103,7 @@ files:
|
|
86
103
|
- lib/xapian_db/stopwords/ru.txt
|
87
104
|
- lib/xapian_db/stopwords/sv.txt
|
88
105
|
- lib/xapian_db/stopwords/update_stopwords.rb
|
106
|
+
- lib/xapian_db/utilities.rb
|
89
107
|
- lib/xapian_db.rb
|
90
108
|
- tasks/beanstalk_worker.rake
|
91
109
|
- xapian_source/xapian-bindings-1.2.4.tar.gz
|
@@ -113,17 +131,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
131
|
requirements:
|
114
132
|
- - ">="
|
115
133
|
- !ruby/object:Gem::Version
|
134
|
+
segments:
|
135
|
+
- 0
|
116
136
|
version: "0"
|
117
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
138
|
none: false
|
119
139
|
requirements:
|
120
140
|
- - ">="
|
121
141
|
- !ruby/object:Gem::Version
|
142
|
+
segments:
|
143
|
+
- 1
|
144
|
+
- 3
|
145
|
+
- 6
|
122
146
|
version: 1.3.6
|
123
147
|
requirements: []
|
124
148
|
|
125
149
|
rubyforge_project:
|
126
|
-
rubygems_version: 1.
|
150
|
+
rubygems_version: 1.3.7
|
127
151
|
signing_key:
|
128
152
|
specification_version: 3
|
129
153
|
summary: Ruby library to use a Xapian db as a key/value store with high performance fulltext search
|