picky 4.0.4 → 4.0.5
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/lib/picky/index.rb +1 -1
- data/lib/picky/query/allocation.rb +1 -1
- data/lib/picky/query/indexes.rb +15 -10
- data/lib/picky/query/qualifier_category_mapper.rb +20 -2
- data/lib/picky/query/token.rb +11 -4
- data/lib/picky/search.rb +6 -6
- data/spec/functional/only_spec.rb +52 -0
- data/spec/functional/regression_spec.rb +1 -1
- data/spec/lib/query/indexes_spec.rb +2 -4
- data/spec/lib/query/qualifier_category_mapper_spec.rb +8 -8
- data/spec/lib/query/token_spec.rb +58 -0
- metadata +19 -17
data/lib/picky/index.rb
CHANGED
@@ -239,7 +239,7 @@ module Picky
|
|
239
239
|
#
|
240
240
|
# === Options
|
241
241
|
# * precision: Default is 1 (20% error margin, very fast), up to 5 (5% error margin, slower) makes sense.
|
242
|
-
# * anchor: Where to anchor the
|
242
|
+
# * anchor: Where to anchor the grid.
|
243
243
|
# * ... all options of #category.
|
244
244
|
#
|
245
245
|
def ranged_category category_name, range, options = {}
|
data/lib/picky/query/indexes.rb
CHANGED
@@ -25,16 +25,8 @@ module Picky
|
|
25
25
|
IndexesCheck.check_backends indexes
|
26
26
|
|
27
27
|
@indexes = indexes
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
def map_categories
|
32
|
-
@mapper = Query::QualifierCategoryMapper.new
|
33
|
-
@indexes.each do |index|
|
34
|
-
index.each_category do |category|
|
35
|
-
@mapper.add category
|
36
|
-
end
|
37
|
-
end
|
28
|
+
|
29
|
+
@mapper = QualifierCategoryMapper.new indexes # TODO Move out?
|
38
30
|
end
|
39
31
|
|
40
32
|
# Ignore the categories with these qualifiers.
|
@@ -51,6 +43,19 @@ module Picky
|
|
51
43
|
@ignored_categories += qualifiers.map { |qualifier| @mapper.map qualifier }.compact
|
52
44
|
@ignored_categories.uniq!
|
53
45
|
end
|
46
|
+
|
47
|
+
# Restrict categories to the given ones.
|
48
|
+
#
|
49
|
+
# Functionally equivalent as if indexes didn't
|
50
|
+
# have the categories at all.
|
51
|
+
#
|
52
|
+
# Note: Probably only makes sense when an index
|
53
|
+
# is used in multiple searches. If not, why even
|
54
|
+
# have the categories?
|
55
|
+
#
|
56
|
+
def only *qualifiers
|
57
|
+
@mapper.restrict_to *qualifiers
|
58
|
+
end
|
54
59
|
|
55
60
|
# Returns a number of prepared (sorted, reduced etc.) allocations for the given tokens.
|
56
61
|
#
|
@@ -9,11 +9,16 @@ module Picky
|
|
9
9
|
class QualifierCategoryMapper # :nodoc:all
|
10
10
|
|
11
11
|
attr_reader :mapping
|
12
|
-
|
12
|
+
|
13
13
|
#
|
14
14
|
#
|
15
|
-
def initialize
|
15
|
+
def initialize indexes
|
16
16
|
@mapping = {}
|
17
|
+
indexes.each do |index|
|
18
|
+
index.each_category do |category|
|
19
|
+
add category
|
20
|
+
end
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
#
|
@@ -35,6 +40,19 @@ module Picky
|
|
35
40
|
|
36
41
|
@mapping[qualifier.intern]
|
37
42
|
end
|
43
|
+
|
44
|
+
# Restricts the given categories.
|
45
|
+
#
|
46
|
+
def restrict user_qualified
|
47
|
+
if @restricted
|
48
|
+
user_qualified ? @restricted & user_qualified : @restricted
|
49
|
+
else
|
50
|
+
user_qualified
|
51
|
+
end
|
52
|
+
end
|
53
|
+
def restrict_to *qualifiers
|
54
|
+
@restricted = qualifiers.map { |qualifier| map qualifier }.compact
|
55
|
+
end
|
38
56
|
|
39
57
|
end
|
40
58
|
|
data/lib/picky/query/token.rb
CHANGED
@@ -57,13 +57,20 @@ module Picky
|
|
57
57
|
|
58
58
|
# Translates this token's qualifiers into actual categories.
|
59
59
|
#
|
60
|
-
# Note:
|
61
|
-
#
|
60
|
+
# Note: If this is not done, there is no mapping.
|
61
|
+
# Note: predefined is an Array of mapped categories.
|
62
62
|
#
|
63
|
-
#
|
63
|
+
# TODO Rename @user_defined_categories. It could now also be predefined by the query.
|
64
64
|
#
|
65
65
|
def categorize mapper
|
66
|
-
@user_defined_categories
|
66
|
+
@user_defined_categories ||= extract_predefined mapper
|
67
|
+
end
|
68
|
+
def extract_predefined mapper
|
69
|
+
user_qualified = categorize_with mapper, @qualifiers
|
70
|
+
mapper.restrict user_qualified
|
71
|
+
end
|
72
|
+
def categorize_with mapper, qualifiers
|
73
|
+
qualifiers && qualifiers.map do |qualifier|
|
67
74
|
mapper.map qualifier
|
68
75
|
end.compact
|
69
76
|
end
|
data/lib/picky/search.rb
CHANGED
@@ -8,10 +8,9 @@ module Picky
|
|
8
8
|
# * holds one or more indexes
|
9
9
|
# * offers an interface to query these indexes.
|
10
10
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# (Protip: Use "curl 'localhost:8080/query/path?query=exampletext')" in a Terminal.
|
11
|
+
# Example:
|
12
|
+
# search = Picky::Search.new index1, index2
|
13
|
+
# search.search 'query'
|
15
14
|
#
|
16
15
|
class Search
|
17
16
|
|
@@ -25,6 +24,7 @@ module Picky
|
|
25
24
|
:boosts
|
26
25
|
|
27
26
|
delegate :ignore,
|
27
|
+
:only,
|
28
28
|
:to => :indexes
|
29
29
|
|
30
30
|
# Takes:
|
@@ -38,8 +38,8 @@ module Picky
|
|
38
38
|
# [:title, :isbn] => +1
|
39
39
|
# end
|
40
40
|
#
|
41
|
-
def initialize *
|
42
|
-
@indexes = Query::Indexes.new *
|
41
|
+
def initialize *indexes
|
42
|
+
@indexes = Query::Indexes.new *indexes
|
43
43
|
|
44
44
|
instance_eval(&Proc.new) if block_given?
|
45
45
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'Search#only' do
|
6
|
+
|
7
|
+
it 'offers the option only' do
|
8
|
+
index = Picky::Index.new :only do
|
9
|
+
category :text1
|
10
|
+
category :text2
|
11
|
+
category :text3
|
12
|
+
end
|
13
|
+
|
14
|
+
index.add Struct.new(:id, :text1, :text2, :text3).new(1, 'text1', 'text2', 'text3')
|
15
|
+
|
16
|
+
try = Picky::Search.new index
|
17
|
+
try.search('text1').ids.should == [1]
|
18
|
+
try.search('text2').ids.should == [1]
|
19
|
+
try.search('text3').ids.should == [1]
|
20
|
+
|
21
|
+
try_again = Picky::Search.new index do
|
22
|
+
only :text1
|
23
|
+
end
|
24
|
+
try_again.search('text1').ids.should == [1]
|
25
|
+
try_again.search('text2').ids.should == []
|
26
|
+
try_again.search('text3').ids.should == []
|
27
|
+
|
28
|
+
try_again.only :text2, :text3
|
29
|
+
try_again.search('text1').ids.should == []
|
30
|
+
try_again.search('text2').ids.should == [1]
|
31
|
+
try_again.search('text3').ids.should == [1]
|
32
|
+
|
33
|
+
try_again.search('text1:text1').ids.should == []
|
34
|
+
try_again.search('text2:text2').ids.should == [1]
|
35
|
+
try_again.search('text3:text3').ids.should == [1]
|
36
|
+
|
37
|
+
try_again.search('text1,text2,text3:text1').ids.should == []
|
38
|
+
try_again.search('text1,text2:text1').ids.should == []
|
39
|
+
try_again.search('text1,text3:text1').ids.should == []
|
40
|
+
try_again.search('text2,text3:text1').ids.should == []
|
41
|
+
|
42
|
+
try_again.search('text1,text2,text3:text2').ids.should == [1]
|
43
|
+
try_again.search('text1,text2:text2').ids.should == [1]
|
44
|
+
try_again.search('text1,text3:text2').ids.should == []
|
45
|
+
try_again.search('text2,text3:text2').ids.should == [1]
|
46
|
+
|
47
|
+
try_again.search('text1,text2,text3:text3').ids.should == [1]
|
48
|
+
try_again.search('text1,text2:text3').ids.should == []
|
49
|
+
try_again.search('text1,text3:text3').ids.should == [1]
|
50
|
+
try_again.search('text2,text3:text3').ids.should == [1]
|
51
|
+
end
|
52
|
+
end
|
@@ -7,10 +7,8 @@ describe Picky::Query::Indexes do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
3.times do |i|
|
10
|
-
|
11
|
-
name
|
12
|
-
indexed = :"indexed#{n}"
|
13
|
-
let(name) { stub name, :internal_indexed => stub(indexed) }
|
10
|
+
name = :"index#{i+1}"
|
11
|
+
let(name) { Picky::Index.new(name) }
|
14
12
|
end
|
15
13
|
|
16
14
|
let(:indexes) do
|
@@ -2,15 +2,15 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Picky::Query::QualifierCategoryMapper do
|
4
4
|
|
5
|
-
let(:
|
6
|
-
|
7
|
-
@category1 =
|
8
|
-
@category2 =
|
9
|
-
@category3 =
|
10
|
-
|
11
|
-
mapper.add @category2
|
12
|
-
mapper.add @category3
|
5
|
+
let(:index) do
|
6
|
+
categories = Picky::Index.new :categories
|
7
|
+
@category1 = categories.category :category1, :qualifiers => ['t1', 'tt1', 'ttt1']
|
8
|
+
@category2 = categories.category :category2, :qualifiers => [:t2, :tt2, :ttt2]
|
9
|
+
@category3 = categories.category :category3, :qualifiers => [:t3, :tt3, :ttt3]
|
10
|
+
categories
|
13
11
|
end
|
12
|
+
let(:indexes) { [index] }
|
13
|
+
let(:mapper) { described_class.new indexes }
|
14
14
|
|
15
15
|
def self.it_should_map(qualifier, expected)
|
16
16
|
it "should map #{qualifier} to #{expected}" do
|
@@ -11,6 +11,64 @@ describe Picky::Query::Token do
|
|
11
11
|
described_class.processed('similar~', 'Similar~').should_not == described_class.processed('similar', 'Similar')
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
describe 'categorize' do
|
16
|
+
let(:mapper) do
|
17
|
+
categories = Picky::Index.new :categories
|
18
|
+
@category1 = categories.category :category1
|
19
|
+
@category2 = categories.category :category2
|
20
|
+
@category3 = categories.category :category3
|
21
|
+
Picky::Query::QualifierCategoryMapper.new [categories]
|
22
|
+
end
|
23
|
+
context 'with qualifiers' do
|
24
|
+
let(:token) { described_class.processed 'category1:qualifier', 'category1:Qualifier' }
|
25
|
+
context 'unrestricted' do
|
26
|
+
it 'categorizes correctly' do
|
27
|
+
token.categorize(mapper).should == [@category1]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
context 'restricted' do
|
31
|
+
before(:each) do
|
32
|
+
mapper.restrict_to :category1
|
33
|
+
end
|
34
|
+
it 'categorizes correctly' do
|
35
|
+
token.categorize(mapper).should == [@category1]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
context 'restricted' do
|
39
|
+
before(:each) do
|
40
|
+
mapper.restrict_to :category2, :category3
|
41
|
+
end
|
42
|
+
it 'categorizes correctly' do
|
43
|
+
token.categorize(mapper).should == []
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
context 'without qualifiers' do
|
48
|
+
let(:token) { described_class.processed 'noqualifier', 'NoQualifier' }
|
49
|
+
context 'unrestricted' do
|
50
|
+
it 'categorizes correctly' do
|
51
|
+
token.categorize(mapper).should == nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
context 'restricted' do
|
55
|
+
before(:each) do
|
56
|
+
mapper.restrict_to :category1
|
57
|
+
end
|
58
|
+
it 'categorizes correctly' do
|
59
|
+
token.categorize(mapper).should == [@category1]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
context 'restricted' do
|
63
|
+
before(:each) do
|
64
|
+
mapper.restrict_to :category2, :category3
|
65
|
+
end
|
66
|
+
it 'categorizes correctly' do
|
67
|
+
token.categorize(mapper).should == [@category2, @category3]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
14
72
|
|
15
73
|
describe 'similar_tokens_for' do
|
16
74
|
let(:token) { described_class.processed 'similar~', 'Similar~' }
|
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: 4.0.
|
4
|
+
version: 4.0.5
|
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: 2011-12-
|
12
|
+
date: 2011-12-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70174977200100 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,21 +21,21 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70174977200100
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: picky-client
|
27
|
-
requirement: &
|
27
|
+
requirement: &70174977199140 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 4.0.
|
32
|
+
version: 4.0.5
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70174977199140
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: text
|
38
|
-
requirement: &
|
38
|
+
requirement: &70174977198140 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70174977198140
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: yajl-ruby
|
49
|
-
requirement: &
|
49
|
+
requirement: &70174977197100 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70174977197100
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: activesupport
|
60
|
-
requirement: &
|
60
|
+
requirement: &70174977195740 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '3.0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70174977195740
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: procrastinate
|
71
|
-
requirement: &
|
71
|
+
requirement: &70174977194540 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0.4'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70174977194540
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rack_fast_escape
|
82
|
-
requirement: &
|
82
|
+
requirement: &70174977192780 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70174977192780
|
91
91
|
description: Fast Ruby semantic text search engine with comfortable single field interface.
|
92
92
|
email: florian.hanke+picky@gmail.com
|
93
93
|
executables:
|
@@ -247,6 +247,7 @@ files:
|
|
247
247
|
- spec/functional/dynamic_weights_spec.rb
|
248
248
|
- spec/functional/exact_first_spec.rb
|
249
249
|
- spec/functional/max_allocations_spec.rb
|
250
|
+
- spec/functional/only_spec.rb
|
250
251
|
- spec/functional/realtime_spec.rb
|
251
252
|
- spec/functional/regression_spec.rb
|
252
253
|
- spec/functional/speed_spec.rb
|
@@ -390,6 +391,7 @@ test_files:
|
|
390
391
|
- spec/functional/dynamic_weights_spec.rb
|
391
392
|
- spec/functional/exact_first_spec.rb
|
392
393
|
- spec/functional/max_allocations_spec.rb
|
394
|
+
- spec/functional/only_spec.rb
|
393
395
|
- spec/functional/realtime_spec.rb
|
394
396
|
- spec/functional/regression_spec.rb
|
395
397
|
- spec/functional/speed_spec.rb
|