picky 3.1.11 → 3.1.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -30,16 +30,26 @@ module Picky
30
30
  @mapping_file = Memory::JSON.new "#{cache_path}.file_mapping.#{extension}"
31
31
  end
32
32
 
33
+ # The default extension for index files is "index".
34
+ #
35
+ def extension
36
+ :index
37
+ end
38
+
33
39
  # The initial content before loading.
34
40
  #
35
- def default
41
+ # Note: We could also load the mapping file
42
+ # as in #load.
43
+ #
44
+ def initial
36
45
  nil
37
46
  end
38
47
 
39
- # The default extension for index files is "index".
48
+ # The empty index that is used for putting the index
49
+ # together before it is saved into the files.
40
50
  #
41
- def extension
42
- :index
51
+ def empty
52
+ {}
43
53
  end
44
54
 
45
55
  # Will copy the index file to a location that
@@ -10,25 +10,25 @@ module Picky
10
10
  #
11
11
  class File < Backend
12
12
 
13
- # Returns an object that responds to:
13
+ # Returns an object that on #initial, #load returns an object that responds to:
14
14
  # [:token] # => [id, id, id, id, id] (an array of ids)
15
15
  #
16
16
  def create_inverted bundle
17
17
  JSON.new bundle.index_path(:inverted)
18
18
  end
19
- # Returns an object that responds to:
19
+ # Returns an object that on #initial, #load returns an object that responds to:
20
20
  # [:token] # => 1.23 (a weight)
21
21
  #
22
22
  def create_weights bundle
23
23
  JSON.new bundle.index_path(:weights)
24
24
  end
25
- # Returns an object that responds to:
25
+ # Returns an object that on #initial, #load returns an object that responds to:
26
26
  # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
27
27
  #
28
28
  def create_similarity bundle
29
29
  JSON.new bundle.index_path(:similarity)
30
30
  end
31
- # Returns an object that responds to:
31
+ # Returns an object that on #initial, #load returns an object that responds to:
32
32
  # [:key] # => value (a value for this config key)
33
33
  #
34
34
  def create_configuration bundle
@@ -32,6 +32,13 @@ module Picky
32
32
  :index
33
33
  end
34
34
 
35
+ # The empty index that is used for putting the index
36
+ # together before it is dumped into the files.
37
+ #
38
+ def empty
39
+ {}
40
+ end
41
+
35
42
  # Will copy the index file to a location that
36
43
  # is in a directory named "backup" right under
37
44
  # the directory the index file is in.
@@ -16,7 +16,7 @@ module Picky
16
16
 
17
17
  # The initial content before loading.
18
18
  #
19
- def default
19
+ def initial
20
20
  {}
21
21
  end
22
22
 
@@ -16,7 +16,7 @@ module Picky
16
16
 
17
17
  # The initial content before loading.
18
18
  #
19
- def default
19
+ def initial
20
20
  {}
21
21
  end
22
22
 
@@ -18,8 +18,8 @@ module Picky
18
18
 
19
19
  # The initial content before loading.
20
20
  #
21
- def default
22
- raise "Can't have a default content from text file. Use JSON or Marshal."
21
+ def initial
22
+ raise "Can't have an initial content from text file. Use JSON or Marshal."
23
23
  end
24
24
 
25
25
  # Text files are used exclusively for
@@ -4,25 +4,25 @@ module Picky
4
4
 
5
5
  class Memory < Backend
6
6
 
7
- # Returns an object that responds to:
7
+ # Returns an object that on #initial, #load returns an object that responds to:
8
8
  # [:token] # => [id, id, id, id, id] (an array of ids)
9
9
  #
10
10
  def create_inverted bundle
11
11
  JSON.new bundle.index_path(:inverted)
12
12
  end
13
- # Returns an object that responds to:
13
+ # Returns an object that on #initial, #load returns an object that responds to:
14
14
  # [:token] # => 1.23 (a weight)
15
15
  #
16
16
  def create_weights bundle
17
17
  JSON.new bundle.index_path(:weights)
18
18
  end
19
- # Returns an object that responds to:
19
+ # Returns an object that on #initial, #load returns an object that responds to:
20
20
  # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
21
21
  #
22
22
  def create_similarity bundle
23
23
  Marshal.new bundle.index_path(:similarity)
24
24
  end
25
- # Returns an object that responds to:
25
+ # Returns an object that on #initial, #load returns an object that responds to:
26
26
  # [:key] # => value (a value for this config key)
27
27
  #
28
28
  def create_configuration bundle
@@ -25,8 +25,11 @@ module Picky
25
25
 
26
26
  # The initial content before loading.
27
27
  #
28
- def default
29
- nil
28
+ # Note: As Redis indexes needn't be loaded per se,
29
+ # this just returns the same thing as #load.
30
+ #
31
+ def initial
32
+ self
30
33
  end
31
34
 
32
35
  # Returns itself.
@@ -35,6 +38,13 @@ module Picky
35
38
  self
36
39
  end
37
40
 
41
+ # The empty index that is used for putting the index
42
+ # together.
43
+ #
44
+ def empty
45
+ {}
46
+ end
47
+
38
48
  # We do not use Redis to retrieve data.
39
49
  #
40
50
  def retrieve
@@ -12,25 +12,25 @@ module Picky
12
12
  @client = options[:client] || ::Redis.new(:db => (options[:db] || 15))
13
13
  end
14
14
 
15
- # Returns an object that responds to:
15
+ # Returns an object that on #initial, #load returns an object that responds to:
16
16
  # [:token] # => [id, id, id, id, id] (an array of ids)
17
17
  #
18
18
  def create_inverted bundle
19
19
  List.new client, "#{bundle.identifier}:inverted"
20
20
  end
21
- # Returns an object that responds to:
21
+ # Returns an object that on #initial, #load returns an object that responds to:
22
22
  # [:token] # => 1.23 (a weight)
23
23
  #
24
24
  def create_weights bundle
25
25
  Float.new client, "#{bundle.identifier}:weights"
26
26
  end
27
- # Returns an object that responds to:
27
+ # Returns an object that on #initial, #load returns an object that responds to:
28
28
  # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
29
29
  #
30
30
  def create_similarity bundle
31
31
  List.new client, "#{bundle.identifier}:similarity"
32
32
  end
33
- # Returns an object that responds to:
33
+ # Returns an object that on #initial, #load returns an object that responds to:
34
34
  # [:key] # => value (a value for this config key)
35
35
  #
36
36
  def create_configuration bundle
data/lib/picky/bundle.rb CHANGED
@@ -44,8 +44,9 @@ module Picky
44
44
  delegate :index_directory, :to => :category
45
45
 
46
46
  def initialize name, category, backend, weights_strategy, partial_strategy, similarity_strategy, options = {}
47
- @name = name
48
- @category = category
47
+ @name = name
48
+ @category = category
49
+
49
50
  @weights_strategy = weights_strategy
50
51
  @partial_strategy = partial_strategy
51
52
  @similarity_strategy = similarity_strategy
@@ -3,25 +3,10 @@ module Picky
3
3
  class Categories
4
4
 
5
5
  each_delegate :remove,
6
+ :add,
7
+ :replace,
6
8
  :to => :categories
7
9
 
8
- # TODO Rewrite indexing/tokenizer/caching etc.
9
- #
10
- def add object
11
- id = object.id
12
- categories.each do |category|
13
- tokens, _ = category.tokenizer.tokenize object.send(category.from).to_s
14
- category.add id, tokens
15
- end
16
- end
17
-
18
- # TODO
19
- #
20
- def replace object
21
- remove object.id
22
- add object
23
- end
24
-
25
10
  end
26
11
 
27
12
  end
@@ -1,25 +1,41 @@
1
1
  module Picky
2
2
 
3
- # TODO
4
- #
5
3
  class Category
6
4
 
7
- # TODO
5
+ # Removes an indexed object with the
6
+ # given id.
8
7
  #
9
8
  def remove id
10
9
  indexed_exact.remove id
11
10
  indexed_partial.remove id
12
11
  end
13
12
 
14
- # TODO
13
+ # Adds and indexes this category of the
14
+ # given object.
15
15
  #
16
- def add id, tokens
16
+ def add object
17
+ tokens, _ = tokenizer.tokenize object.send(from).to_s
18
+ add_tokenized object.id, tokens
19
+ end
20
+
21
+ # Removes the object's id, and then
22
+ # adds it again.
23
+ #
24
+ def replace object
25
+ remove object.id
26
+ add object
27
+ end
28
+
29
+ # For the given id, adds the list of
30
+ # strings to the index for the given id.
31
+ #
32
+ def add_tokenized id, tokens
17
33
  tokens.each do |text|
18
34
  next unless text
19
35
  text = text.to_sym
20
36
  indexed_exact.add id, text
21
37
 
22
- # TODO Refactor.
38
+ # TODO Refactor. Push into indexed_partial?
23
39
  #
24
40
  indexed_partial.partial_strategy.each_partial text do |partial_text|
25
41
  indexed_partial.add id, partial_text
@@ -23,10 +23,10 @@ module Picky
23
23
  def initialize name, category, backend, weights_strategy, partial_strategy, similarity_strategy, options = {}
24
24
  super name, category, backend, weights_strategy, partial_strategy, similarity_strategy, options
25
25
 
26
- @inverted = @backend_inverted.default
27
- @weights = @backend_weights.default
28
- @similarity = @backend_similarity.default
29
- @configuration = @backend_configuration.default
26
+ @inverted = @backend_inverted.initial
27
+ @weights = @backend_weights.initial
28
+ @similarity = @backend_similarity.initial
29
+ @configuration = @backend_configuration.initial
30
30
 
31
31
  @realtime_mapping = {} # id -> ary of syms. TODO Always instantiate?
32
32
  end
@@ -21,7 +21,9 @@ module Picky
21
21
  if ids.empty?
22
22
  @inverted.delete sym
23
23
  @weights.delete sym
24
- @similarity.delete encoded # Since no element uses this sym anymore, we can delete the similarity for it.
24
+ # Since no element uses this sym anymore, we can delete the similarity for it.
25
+ # TODO Not really. Since multiple syms can point to the same encoded.
26
+ @similarity.delete encoded
25
27
  else
26
28
  @weights[sym] = self.weights_strategy.weight_for ids.size
27
29
  end
@@ -43,10 +43,10 @@ module Picky
43
43
  @key_format = options[:key_format]
44
44
  @prepared = Backends::Memory::Text.new category.prepared_index_path
45
45
 
46
- @inverted = {}
47
- @weights = {}
48
- @similarity = {}
49
- @configuration = {}
46
+ @inverted = @backend_inverted.empty
47
+ @weights = @backend_weights.empty
48
+ @similarity = @backend_similarity.empty
49
+ @configuration = @backend_configuration.empty
50
50
  end
51
51
 
52
52
  # Sets up a piece of the index for the given token.
@@ -2,23 +2,29 @@ require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::Basic do
4
4
 
5
- let(:file) { described_class.new 'some/cache/path/to/file' }
6
-
5
+ let(:basic) { described_class.new 'some/cache/path/to/file' }
6
+
7
+ describe 'empty' do
8
+ it 'returns the container that is used for indexing' do
9
+ basic.empty.should == {}
10
+ end
11
+ end
12
+
7
13
  describe 'backup_file_path_of' do
8
14
  it 'returns a backup path relative to the path' do
9
- file.backup_file_path_of('some/path/to/some.memory.index').should == 'some/path/to/backup/some.memory.index'
15
+ basic.backup_file_path_of('some/path/to/some.memory.index').should == 'some/path/to/backup/some.memory.index'
10
16
  end
11
17
  end
12
18
 
13
19
  describe 'backup_directory' do
14
20
  it "returns the cache path's backup path" do
15
- file.backup_directory('some/cache/path/to/file').should == 'some/cache/path/to/backup'
21
+ basic.backup_directory('some/cache/path/to/file').should == 'some/cache/path/to/backup'
16
22
  end
17
23
  end
18
24
 
19
25
  describe 'to_s' do
20
26
  it 'returns the cache path with the default file extension' do
21
- file.to_s.should == 'Picky::Backends::Memory::Basic(some/cache/path/to/file.memory.index)'
27
+ basic.to_s.should == 'Picky::Backends::Memory::Basic(some/cache/path/to/file.memory.index)'
22
28
  end
23
29
  end
24
30
 
@@ -2,29 +2,43 @@ require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::JSON do
4
4
 
5
- let(:file) { described_class.new 'some/cache/path/to/file' }
6
-
7
- describe "dump" do
8
- it "delegates to the given hash" do
9
- hash = stub :hash
10
-
11
- hash.should_receive(:dump_json).once.with "some/cache/path/to/file.memory.json"
12
-
13
- file.dump hash
5
+ context 'hash-based indexes' do
6
+ let(:json) { described_class.new 'some/cache/path/to/file' }
7
+
8
+ describe 'extension' do
9
+ it 'is correct' do
10
+ json.extension.should == :json
11
+ end
14
12
  end
15
- end
16
-
17
- describe "retrieve" do
18
- it "raises" do
19
- lambda do
20
- file.retrieve
21
- end.should raise_error("Can't retrieve from JSON file. Use text file.")
13
+
14
+ describe 'initial' do
15
+ it 'is correct' do
16
+ json.initial.should == {}
17
+ end
22
18
  end
23
- end
24
-
25
- describe 'to_s' do
26
- it 'returns the cache path with the default file extension' do
27
- file.to_s.should == 'Picky::Backends::Memory::JSON(some/cache/path/to/file.memory.json)'
19
+
20
+ describe "dump" do
21
+ it "delegates to the given hash" do
22
+ hash = stub :hash
23
+
24
+ hash.should_receive(:dump_json).once.with "some/cache/path/to/file.memory.json"
25
+
26
+ json.dump hash
27
+ end
28
+ end
29
+
30
+ describe "retrieve" do
31
+ it "raises" do
32
+ lambda do
33
+ json.retrieve
34
+ end.should raise_error("Can't retrieve from JSON file. Use text file.")
35
+ end
36
+ end
37
+
38
+ describe 'to_s' do
39
+ it 'returns the cache path with the default file extension' do
40
+ json.to_s.should == 'Picky::Backends::Memory::JSON(some/cache/path/to/file.memory.json)'
41
+ end
28
42
  end
29
43
  end
30
44
 
@@ -2,29 +2,43 @@ require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::Marshal do
4
4
 
5
- let(:file) { described_class.new 'some/cache/path/to/file' }
5
+ context 'hash-based indexes' do
6
+ let(:marshal) { described_class.new 'some/cache/path/to/file' }
6
7
 
7
- describe "dump" do
8
- it "delegates to the given hash" do
9
- hash = stub :hash
8
+ describe 'extension' do
9
+ it 'is correct' do
10
+ marshal.extension.should == :dump
11
+ end
12
+ end
13
+
14
+ describe 'initial' do
15
+ it 'is correct' do
16
+ marshal.initial.should == {}
17
+ end
18
+ end
19
+
20
+ describe "dump" do
21
+ it "delegates to the given hash" do
22
+ hash = stub :hash
10
23
 
11
- hash.should_receive(:dump_marshal).once.with "some/cache/path/to/file.memory.dump"
24
+ hash.should_receive(:dump_marshal).once.with "some/cache/path/to/file.memory.dump"
12
25
 
13
- file.dump hash
26
+ marshal.dump hash
27
+ end
14
28
  end
15
- end
16
29
 
17
- describe "retrieve" do
18
- it "raises" do
19
- lambda do
20
- file.retrieve
21
- end.should raise_error("Can't retrieve from marshalled file. Use text file.")
30
+ describe "retrieve" do
31
+ it "raises" do
32
+ lambda do
33
+ marshal.retrieve
34
+ end.should raise_error("Can't retrieve from marshalled file. Use text file.")
35
+ end
22
36
  end
23
- end
24
37
 
25
- describe 'to_s' do
26
- it 'returns the cache path with the default file extension' do
27
- file.to_s.should == 'Picky::Backends::Memory::Marshal(some/cache/path/to/file.memory.dump)'
38
+ describe 'to_s' do
39
+ it 'returns the cache path with the default file extension' do
40
+ marshal.to_s.should == 'Picky::Backends::Memory::Marshal(some/cache/path/to/file.memory.dump)'
41
+ end
28
42
  end
29
43
  end
30
44
 
@@ -2,21 +2,33 @@ require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::Text do
4
4
 
5
- before(:each) do
6
- @file = described_class.new "some_cache_path"
5
+ let(:text) { described_class.new "some_cache_path" }
6
+
7
+ describe 'extension' do
8
+ it 'is correct' do
9
+ text.extension.should == :txt
10
+ end
11
+ end
12
+
13
+ describe 'initial' do
14
+ it 'raises' do
15
+ expect {
16
+ text.initial
17
+ }.to raise_error("Can't have an initial content from text file. Use JSON or Marshal.")
18
+ end
7
19
  end
8
20
 
9
21
  describe "load" do
10
22
  it "raises" do
11
23
  lambda do
12
- @file.load
24
+ text.load
13
25
  end.should raise_error("Can't load from text file. Use JSON or Marshal.")
14
26
  end
15
27
  end
16
28
  describe "dump" do
17
29
  it "raises" do
18
30
  lambda do
19
- @file.dump :anything
31
+ text.dump :anything
20
32
  end.should raise_error("Can't dump to text file. Use JSON or Marshal.")
21
33
  end
22
34
  end
@@ -27,13 +39,13 @@ describe Picky::Backends::Memory::Text do
27
39
  ::File.should_receive(:open).any_number_of_times.and_yield @io
28
40
  end
29
41
  it "yields split lines and returns the id and token text" do
30
- @file.retrieve do |id, token|
42
+ text.retrieve do |id, token|
31
43
  id.should == '123456'
32
44
  token.should == :some_nice_token
33
45
  end
34
46
  end
35
47
  it "is fast" do
36
- performance_of { @file.retrieve { |id, token| } }.should < 0.00005
48
+ performance_of { text.retrieve { |id, token| } }.should < 0.00005
37
49
  end
38
50
  end
39
51
 
@@ -16,6 +16,18 @@ describe Picky::Backends::Redis::Basic do
16
16
  end
17
17
  end
18
18
 
19
+ describe 'empty' do
20
+ it 'returns the container that is used for indexing' do
21
+ index.empty.should == {}
22
+ end
23
+ end
24
+
25
+ describe 'initial' do
26
+ it 'is correct' do
27
+ index.initial.class.should == described_class
28
+ end
29
+ end
30
+
19
31
  describe 'cache_small?' do
20
32
  context 'size 0' do
21
33
  before(:each) do
@@ -12,7 +12,7 @@ describe "Realtime Indexing" do
12
12
  end
13
13
 
14
14
  let(:index) do
15
- Picky::Index.new(:test) do
15
+ Picky::Index.new(:books) do
16
16
  source []
17
17
  category :title
18
18
  category :author, similarity: Picky::Generators::Similarity::DoubleMetaphone.new(3)
@@ -24,6 +24,39 @@ describe "Realtime Indexing" do
24
24
  index.add Book.new(1, "Title", "Author")
25
25
  end
26
26
 
27
+ context 'single category updating' do
28
+ it 'finds the first entry' do
29
+ books.search('title:Titl').ids.should == [1]
30
+ end
31
+
32
+ it 'allows removing a single category and leaving the others alone' do
33
+ index[:title].remove 1
34
+
35
+ books.search('Title').ids.should == []
36
+ books.search('Author').ids.should == [1]
37
+ end
38
+
39
+ it 'allows adding a single category and leaving the others alone' do
40
+ index[:title].add Book.new(2, "Newtitle", "Newauthor")
41
+
42
+ books.search('Title').ids.should == [1]
43
+ books.search('Newtitle').ids.should == [2]
44
+
45
+ books.search('Author').ids.should == [1]
46
+ books.search('Newauthor').ids.should == []
47
+ end
48
+
49
+ it 'allows replacing a single category and leaving the others alone' do
50
+ index[:title].replace Book.new(1, "Replaced", "Notindexed")
51
+
52
+ books.search('Title').ids.should == []
53
+ books.search('Replaced').ids.should == [1]
54
+
55
+ books.search('Notindexed').ids.should == []
56
+ books.search('Author').ids.should == [1]
57
+ end
58
+ end
59
+
27
60
  context 'with partial' do
28
61
  it 'finds the first entry' do
29
62
  books.search('Titl').ids.should == [1]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picky
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.11
4
+ version: 3.1.12
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-24 00:00:00.000000000 +11:00
13
- default_executable: picky
12
+ date: 2011-10-26 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: rspec
17
- requirement: &70264818405600 !ruby/object:Gem::Requirement
16
+ requirement: &70305699965140 !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
@@ -22,18 +21,18 @@ dependencies:
22
21
  version: '0'
23
22
  type: :development
24
23
  prerelease: false
25
- version_requirements: *70264818405600
24
+ version_requirements: *70305699965140
26
25
  - !ruby/object:Gem::Dependency
27
26
  name: picky-client
28
- requirement: &70264818404920 !ruby/object:Gem::Requirement
27
+ requirement: &70305699964660 !ruby/object:Gem::Requirement
29
28
  none: false
30
29
  requirements:
31
30
  - - =
32
31
  - !ruby/object:Gem::Version
33
- version: 3.1.11
32
+ version: 3.1.12
34
33
  type: :development
35
34
  prerelease: false
36
- version_requirements: *70264818404920
35
+ version_requirements: *70305699964660
37
36
  description: Fast Ruby semantic text search engine with comfortable single field interface.
38
37
  email: florian.hanke+picky@gmail.com
39
38
  executables:
@@ -269,7 +268,6 @@ files:
269
268
  - spec/specific/realtime_spec.rb
270
269
  - spec/specific/speed_spec.rb
271
270
  - bin/picky
272
- has_rdoc: true
273
271
  homepage: http://florianhanke.com/picky
274
272
  licenses: []
275
273
  post_install_message:
@@ -290,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
290
288
  version: '0'
291
289
  requirements: []
292
290
  rubyforge_project: http://rubyforge.org/projects/picky
293
- rubygems_version: 1.6.2
291
+ rubygems_version: 1.8.10
294
292
  signing_key:
295
293
  specification_version: 3
296
294
  summary: ! 'Picky: Semantic Search Engine. Clever Interface. Good Tools.'