picky 4.5.11 → 4.5.12

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.
@@ -3,14 +3,27 @@ module Picky
3
3
  class Index
4
4
 
5
5
  # Return facets for a category in the form:
6
- # { text => weight } # or ids.size?
6
+ # { text => count }
7
+ #
8
+ # Options
9
+ # counts: Whether you want counts or not.
10
+ # at_least: A minimum count a facet needs to have (inclusive).
11
+ #
12
+ # TODO Think about having a separate index for counts to reduce the complexity of this.
7
13
  #
8
14
  def facets category_identifier, options = {}
9
- weights = self[category_identifier].exact.weights
10
- if minimal_weight = options[:more_than]
11
- weights.select { |_, weight| weight > minimal_weight }
12
- else
13
- weights
15
+ text_ids = self[category_identifier].exact.inverted
16
+ no_counts = options[:counts] == false
17
+ minimal_counts = options[:at_least]
18
+ text_ids.inject(no_counts ? [] : {}) do |result, text_ids|
19
+ text, ids = text_ids
20
+ size = ids.size
21
+ next result if minimal_counts && size < minimal_counts
22
+ if no_counts
23
+ result << text
24
+ else
25
+ result[text] = size; result
26
+ end
14
27
  end
15
28
  end
16
29
 
@@ -2,13 +2,14 @@ module Picky
2
2
 
3
3
  class Search
4
4
 
5
- # Returns a list of filtered facets.
5
+ # Returns a list/hash of filtered facets.
6
6
  #
7
7
  # Params
8
8
  # category: The category whose facets to return.
9
9
  #
10
10
  # Options
11
- # more_than: A minimum weight a facet needs to have (exclusive).
11
+ # counts: Whether you want counts (returns a Hash) or not (returns an Array).
12
+ # at_least: A minimum count a facet needs to have (inclusive).
12
13
  # filter: A query to filter the facets with.
13
14
  #
14
15
  # Usage:
@@ -18,23 +19,38 @@ module Picky
18
19
  raise "#{__method__} cannot be used on searches with more than 1 index yet. Sorry!" if indexes.size > 1
19
20
  index = indexes.first
20
21
 
21
- # Get index-specific facet weights.
22
+ # Get index-specific facet counts.
22
23
  #
23
- weights = index.facets category_identifier, options
24
+ counts = index.facets category_identifier, options
24
25
 
25
26
  # We're done if there is no filter.
26
27
  #
27
- return weights unless filter_query = options[:filter]
28
+ return counts unless filter_query = options[:filter]
28
29
 
29
30
  # Pre-tokenize filter for reuse.
30
31
  #
31
32
  tokenized_filter = tokenized filter_query, false
32
33
 
33
- # Filter out impossible facets.
34
+ # Extract options.
34
35
  #
35
- weights.select do |key, weight|
36
+ no_counts = options[:counts] == false
37
+ minimal_counts = options[:at_least] || 1 # Default needs at least one.
38
+
39
+ # Get actual counts.
40
+ #
41
+ # TODO Rewrite.
42
+ #
43
+ counts.inject(no_counts ? [] : {}) do |result, key_count|
44
+ key, _ = key_count
36
45
  tokenized_query = tokenized "#{category_identifier}:#{key}", false
37
- search_with(tokenized_filter + tokenized_query, 0, 0).total > 0
46
+ total = search_with(tokenized_filter + tokenized_query, 0, 0).total
47
+ next result unless total >= minimal_counts
48
+ if no_counts
49
+ result << key
50
+ else
51
+ result[key] = total; result
52
+ end
53
+ result
38
54
  end
39
55
  end
40
56
 
@@ -22,38 +22,38 @@ describe 'facets' do
22
22
  }
23
23
  let(:finder) { Picky::Search.new index }
24
24
 
25
- describe 'facets' do
25
+ describe 'Index#facets' do
26
26
  it 'is correct' do
27
- # Picky has 2 facets with different weights for surname.
27
+ # Picky has 2 facets with different counts for surname.
28
28
  #
29
29
  index.facets(:surname).should == {
30
- 'hanke' => 0.693,
31
- 'schiess' => 0
30
+ 'hanke' => 2,
31
+ 'schiess' => 1
32
32
  }
33
33
 
34
- # It has 3 facets with the same weight for name.
34
+ # It has 3 facets with the same count for name.
35
35
  #
36
36
  index.facets(:name).should == {
37
- 'fritz' => 0,
38
- 'kaspar' => 0,
39
- 'florian' => 0
37
+ 'fritz' => 1,
38
+ 'kaspar' => 1,
39
+ 'florian' => 1
40
40
  }
41
41
 
42
- # Picky only selects facets with a weight >= the given one.
42
+ # Picky only selects facets with a count >= the given one.
43
43
  #
44
- index.facets(:surname, more_than: 0.5).should == {
45
- 'hanke' => 0.693
44
+ index.facets(:surname, at_least: 2).should == {
45
+ 'hanke' => 2
46
46
  }
47
47
  end
48
48
  end
49
49
 
50
- describe 'facets' do
50
+ describe 'Search#facets' do
51
51
  it 'filters them correctly' do
52
52
  # Passing in no filter query just returns the facets
53
53
  #
54
54
  finder.facets(:surname).should == {
55
- 'hanke' => 0.693,
56
- 'schiess' => 0.0
55
+ 'hanke' => 2,
56
+ 'schiess' => 1
57
57
  }
58
58
 
59
59
  # It has two facets.
@@ -61,8 +61,8 @@ describe 'facets' do
61
61
  # TODO Rewrite API.
62
62
  #
63
63
  finder.facets(:name, filter: 'surname:hanke').should == {
64
- 'fritz' => 0,
65
- 'florian' => 0
64
+ 'fritz' => 1,
65
+ 'florian' => 1
66
66
  }
67
67
  end
68
68
  end
@@ -88,61 +88,94 @@ describe 'facets' do
88
88
  }
89
89
  let(:finder) { Picky::Search.new index }
90
90
 
91
- describe 'facets' do
92
- it 'is correct' do
93
- # Picky has 2 facets with different weights for surname.
94
- #
91
+ describe 'Index#facets' do
92
+ it 'has 2 facets with different counts for surname' do
95
93
  index.facets(:surname).should == {
96
- 'hanke' => 0.693,
97
- 'kunz' => 0.0,
98
- 'meier' => 1.099
94
+ 'hanke' => 2,
95
+ 'kunz' => 1,
96
+ 'meier' => 3
99
97
  }
100
-
101
- # It has 3 facets with the same weight for name.
102
- #
98
+ end
99
+ it 'has 4 facets for the name' do
103
100
  index.facets(:name).should == {
104
- 'annabelle' => 0.0,
105
- 'hans' => 0.0,
106
- 'peter' => 1.099,
107
- 'ursula' => 0.0
101
+ 'annabelle' => 1,
102
+ 'hans' => 1,
103
+ 'peter' => 3,
104
+ 'ursula' => 1
108
105
  }
109
-
110
- # It has 1 facet with weight > 0.
111
- #
112
- index.facets(:name, more_than: 0).should == {
113
- 'peter' => 1.099
106
+ end
107
+ it 'has 3 facets with the same count for name' do
108
+ index.facets(:name).should == {
109
+ 'annabelle' => 1,
110
+ 'hans' => 1,
111
+ 'peter' => 3,
112
+ 'ursula' => 1
113
+ }
114
+ end
115
+ it 'has 1 facet with count >= 2' do
116
+ index.facets(:name, at_least: 2).should == {
117
+ 'peter' => 3
114
118
  }
115
119
  end
116
120
  end
117
121
 
118
- describe 'facets' do
122
+ describe 'Search#facets' do
119
123
  it 'is fast enough' do
120
124
  performance_of {
121
125
  10.times { finder.facets(:age_category, filter: 'surname:meier name:peter') }
122
126
  }.should < 0.00275
123
127
  end
124
- it 'filters them correctly' do
125
- # It has one facet.
126
- #
128
+ it 'has one filtered facet' do
127
129
  # TODO Fix problems with alternative qualifiers (like :age).
128
130
  #
129
131
  finder.facets(:age_category, filter: 'surname:meier name:peter').should == {
130
- '45' => 0
132
+ '45' => 1
131
133
  }
132
-
133
- # It has two facets.
134
- #
134
+ end
135
+ it 'has two filtered facets' do
135
136
  finder.facets(:surname, filter: 'age_category:40 name:peter').should == {
136
- 'kunz' => 0.0,
137
- 'hanke' => 0.693
137
+ 'kunz' => 1,
138
+ 'hanke' => 1 # Not 2 since it is filtered.
138
139
  }
139
-
140
- # It has 1 facet > weight 0.
141
- #
142
- finder.facets(:surname, filter: 'age_category:40 name:peter', more_than: 0).should == {
143
- 'hanke' => 0.693
140
+ end
141
+ it 'has 2 facets >= count 0' do
142
+ finder.facets(:surname, filter: 'age_category:40 name:peter', at_least: 1).should == {
143
+ 'kunz' => 1,
144
+ 'hanke' => 1
144
145
  }
145
146
  end
147
+ it 'has 0 facets >= counts 2' do
148
+ finder.facets(:surname, filter: 'age_category:40 name:peter', at_least: 2).should == {}
149
+ end
146
150
  end
151
+
152
+ describe 'Search#facets without counts' do
153
+ it 'is fast enough' do
154
+ performance_of {
155
+ 10.times { finder.facets(:age_category, filter: 'surname:meier name:peter', counts: false) }
156
+ }.should < 0.00275
157
+ end
158
+ it 'has one filtered facet' do
159
+ # TODO Fix problems with alternative qualifiers (like :age).
160
+ #
161
+ finder.facets(:age_category, filter: 'surname:meier name:peter', counts: false).should == ['45']
162
+ end
163
+ it 'has two filtered facets' do
164
+ finder.facets(:surname, filter: 'age_category:40 name:peter', counts: false).should == [
165
+ 'kunz',
166
+ 'hanke'
167
+ ]
168
+ end
169
+ it 'has 2 facets >= count 0' do
170
+ finder.facets(:surname, filter: 'age_category:40 name:peter', at_least: 1, counts: false).should == [
171
+ 'kunz',
172
+ 'hanke'
173
+ ]
174
+ end
175
+ it 'has 0 facets >= counts 2' do
176
+ finder.facets(:surname, filter: 'age_category:40 name:peter', at_least: 2, counts: false).should == []
177
+ end
178
+ end
179
+
147
180
  end
148
181
  end
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.5.11
4
+ version: 4.5.12
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-07-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70359044149180 !ruby/object:Gem::Requirement
16
+ requirement: &70303139130820 !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: *70359044149180
24
+ version_requirements: *70303139130820
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: picky-client
27
- requirement: &70359044148680 !ruby/object:Gem::Requirement
27
+ requirement: &70303139130320 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
31
31
  - !ruby/object:Gem::Version
32
- version: 4.5.11
32
+ version: 4.5.12
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70359044148680
35
+ version_requirements: *70303139130320
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: text
38
- requirement: &70359044148260 !ruby/object:Gem::Requirement
38
+ requirement: &70303139129900 !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: *70359044148260
46
+ version_requirements: *70303139129900
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: multi_json
49
- requirement: &70359044147800 !ruby/object:Gem::Requirement
49
+ requirement: &70303139129440 !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: *70359044147800
57
+ version_requirements: *70303139129440
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: activesupport
60
- requirement: &70359044147300 !ruby/object:Gem::Requirement
60
+ requirement: &70303139128940 !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: *70359044147300
68
+ version_requirements: *70303139128940
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: procrastinate
71
- requirement: &70359044146800 !ruby/object:Gem::Requirement
71
+ requirement: &70303139128440 !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: *70359044146800
79
+ version_requirements: *70303139128440
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rack_fast_escape
82
- requirement: &70359044146420 !ruby/object:Gem::Requirement
82
+ requirement: &70303139128060 !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: *70359044146420
90
+ version_requirements: *70303139128060
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: