repertoire-faceting 0.5.2 → 0.5.3
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/FAQ +88 -91
- data/INSTALL +186 -174
- data/README +158 -370
- data/TODO +21 -32
- data/lib/repertoire-faceting/adapters/postgresql_adapter.rb +3 -12
- data/lib/repertoire-faceting/controller.rb +36 -3
- data/lib/repertoire-faceting/model.rb +45 -22
- data/lib/repertoire-faceting/routing.rb +9 -7
- data/lib/repertoire-faceting/version.rb +1 -1
- metadata +3 -3
@@ -21,13 +21,13 @@ module Repertoire
|
|
21
21
|
module PostgreSQLAdapter #:nodoc:
|
22
22
|
|
23
23
|
# Creates (or recreates) the packed id column on a given table
|
24
|
-
def renumber_table(table_name, faceting_id
|
25
|
-
sql = "SELECT renumber_table('#{table_name}', '#{faceting_id}')"
|
24
|
+
def renumber_table(table_name, faceting_id, wastage)
|
25
|
+
sql = "SELECT renumber_table('#{table_name}', '#{faceting_id}', #{wastage})"
|
26
26
|
execute(sql)
|
27
27
|
end
|
28
28
|
|
29
29
|
# Returns the scatter quotient of the given id column
|
30
|
-
def signature_wastage(table_name, faceting_id
|
30
|
+
def signature_wastage(table_name, faceting_id)
|
31
31
|
sql = "SELECT signature_wastage('#{table_name}', '#{faceting_id}')"
|
32
32
|
result = select_value(sql)
|
33
33
|
Float(result)
|
@@ -88,15 +88,6 @@ module Repertoire
|
|
88
88
|
"INNER JOIN members(#{exprs.join(' & ')}) AS _refinements_id ON (#{table_name}.#{faceting_id} = _refinements_id)"
|
89
89
|
end
|
90
90
|
|
91
|
-
private
|
92
|
-
|
93
|
-
def ignoring_db_errors(&block)
|
94
|
-
begin
|
95
|
-
yield
|
96
|
-
rescue
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
91
|
end
|
101
92
|
end
|
102
93
|
end
|
@@ -2,10 +2,43 @@ module Repertoire
|
|
2
2
|
module Faceting #:nodoc:
|
3
3
|
|
4
4
|
# Include this mixin in your controller to add faceting webservices for use with the javascript
|
5
|
-
# widgets.
|
6
|
-
#
|
5
|
+
# widgets. Implementors should over-ride base() to specify the model for the faceted browser.
|
6
|
+
#
|
7
|
+
# class PaintingsController
|
8
|
+
# include Repertoire::Faceting::Controller
|
9
|
+
# def base
|
10
|
+
# Painting
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# By default two web services are defined, one for the facet value count widgets and another for
|
15
|
+
# the result widget. Each builds on the model returned by base():
|
16
|
+
#
|
17
|
+
# counts ==> base.refine(params[:filter]).count(params[:facet])
|
18
|
+
# results ==> base.refine(params[:filter]).to_a
|
19
|
+
#
|
20
|
+
# If desired, you can use the Model API to specify a query that limits the faceting context to
|
21
|
+
# a subset of the available items from the start:
|
22
|
+
#
|
23
|
+
# def base
|
24
|
+
# q = "#{params[:search]}%"
|
25
|
+
# Painting.where(["title like ?", q])
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Finally, you are free to over-ride the counts() and results() webservices. Here we
|
29
|
+
# reorder the facet value counts depending on another webservice param:
|
30
|
+
#
|
31
|
+
# def counts
|
32
|
+
# facet = params[:facet]
|
33
|
+
# filter = params[:filter] || {}
|
34
|
+
# sorting = case params[:order]
|
35
|
+
# when 'alphanumeric' then ["#{facet} ASC"]
|
36
|
+
# when 'count' then ["count DESC", "#{facet} ASC"]
|
37
|
+
# end
|
38
|
+
# @counts = base.refine(filter).order(sorting).count(facet)
|
39
|
+
# render :json => @counts.to_a
|
40
|
+
# end
|
7
41
|
#
|
8
|
-
# However, for more complex behavior you can over-ride counts() and results() as well.
|
9
42
|
module Controller
|
10
43
|
|
11
44
|
# Web-service to return value, count pairs for a given facet, given existing filter refinements
|
@@ -3,6 +3,10 @@ module Repertoire
|
|
3
3
|
module Model #:nodoc:
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
SIGNATURE_WASTAGE_THRESHOLD = 0.15
|
7
|
+
DEFAULT_SIGNATURE_COLUMN = 'id'
|
8
|
+
PACKED_SIGNATURE_COLUMN = '_packed_id'
|
9
|
+
|
6
10
|
included do |base|
|
7
11
|
base.singleton_class.delegate :refine, :minimum, :nils, :reorder, :to_sql, :to => :scoped
|
8
12
|
end
|
@@ -29,8 +33,8 @@ module Repertoire
|
|
29
33
|
#
|
30
34
|
# facet :discipline, group(:discipline)
|
31
35
|
#
|
32
|
-
# and the grouping on degree could be left out. You can use this to construct a facet
|
33
|
-
# named columns:
|
36
|
+
# and the grouping on degree could be left out. You can use this behavior to construct a facet
|
37
|
+
# from differently-named columns:
|
34
38
|
#
|
35
39
|
# facet :balloon_color, group(:color)
|
36
40
|
#
|
@@ -42,13 +46,13 @@ module Repertoire
|
|
42
46
|
#
|
43
47
|
# == Nested facets
|
44
48
|
#
|
45
|
-
# Facets can be
|
49
|
+
# Facets can be built from a nested hierarchy of values by providing multiple group columns. In this
|
46
50
|
# case, value counts are aggregated at each level in turn.
|
47
51
|
#
|
48
52
|
# facet :birth_place, group(:birth_country, :birth_state, :birth_city)
|
49
53
|
#
|
50
|
-
# As for basic facets, nested facets
|
51
|
-
# faceting over data in more complex types such as dates or geographical regions
|
54
|
+
# As for basic facets, nested facets may consist of SQL expressions. This is particularly useful in
|
55
|
+
# faceting over data in more complex types such as dates or geographical regions:
|
52
56
|
#
|
53
57
|
# facet :birth_date, group('EXTRACT(year FROM birthdate)', 'EXTRACT(month FROM birthdate)', 'EXTRACT(day FROM birthdate)')
|
54
58
|
#
|
@@ -137,27 +141,45 @@ module Repertoire
|
|
137
141
|
facets.keys
|
138
142
|
end
|
139
143
|
|
140
|
-
# Drops any unused facet indices, updates its packed ids, then recreates
|
141
|
-
# for the facets with the provided names. If no names are provided,
|
142
|
-
# facet indices are refreshed.
|
144
|
+
# Drops any unused facet indices, updates its packed ids, then recreates
|
145
|
+
# indices for the facets with the provided names. If no names are provided,
|
146
|
+
# then the existing facet indices are refreshed.
|
147
|
+
#
|
148
|
+
# If a signature id column name is provided, it will be used to build the
|
149
|
+
# bitset indices. Otherwise the indexer will add or remove a new packed
|
150
|
+
# id column as appropriate.
|
151
|
+
#
|
152
|
+
# Examples:
|
143
153
|
#
|
144
154
|
# === Refresh existing facet indices
|
145
155
|
#
|
146
156
|
# Nobelist.update_indexed_facets
|
147
157
|
#
|
148
|
-
# ===
|
158
|
+
# === Adjust which facets are indexed
|
159
|
+
#
|
160
|
+
# Nobelist.update_indexed_facets([:degree, :nobel_year])
|
161
|
+
#
|
162
|
+
# === Drop all facet indices, but add/remove packed id as necessary
|
149
163
|
#
|
150
164
|
# Nobelist.update_indexed_facets([])
|
151
165
|
#
|
152
|
-
# ===
|
166
|
+
# === Drop absolutely everything, force manual faceting using 'id'
|
167
|
+
# column
|
153
168
|
#
|
154
|
-
# Nobelist.
|
169
|
+
# Nobelist.udpate_indexed_facets([], 'id')
|
155
170
|
#
|
156
|
-
def update_indexed_facets(facet_names=nil)
|
171
|
+
def update_indexed_facets(facet_names=nil, signature_column=nil)
|
157
172
|
# default: update existing facets
|
158
173
|
indexed_facets = connection.indexed_facets(table_name)
|
159
174
|
facet_names ||= indexed_facets
|
160
175
|
|
176
|
+
# determine best column for signature bitsets, unless set manually
|
177
|
+
signature_column ||= if signature_wastage('id') < SIGNATURE_WASTAGE_THRESHOLD
|
178
|
+
DEFAULT_SIGNATURE_COLUMN
|
179
|
+
else
|
180
|
+
PACKED_SIGNATURE_COLUMN
|
181
|
+
end
|
182
|
+
|
161
183
|
connection.transaction do
|
162
184
|
# drop old facet indices
|
163
185
|
indexed_facets.each do |name|
|
@@ -165,18 +187,14 @@ module Repertoire
|
|
165
187
|
connection.drop_table(table)
|
166
188
|
end
|
167
189
|
|
168
|
-
#
|
169
|
-
|
170
|
-
connection.remove_column(table_name, '_packed_id')
|
171
|
-
else
|
172
|
-
connection.renumber_table(table_name, '_packed_id')
|
173
|
-
end
|
190
|
+
# create or remove packed signature column as necessary
|
191
|
+
ensure_numbering(signature_column)
|
174
192
|
|
175
193
|
# re-create the facet indices
|
176
194
|
facet_names.each do |name|
|
177
195
|
name = name.to_sym
|
178
196
|
raise "Unknown facet #{name}" unless facet?(name)
|
179
|
-
facets[name].create_index(
|
197
|
+
facets[name].create_index(signature_column)
|
180
198
|
end
|
181
199
|
end
|
182
200
|
|
@@ -186,7 +204,7 @@ module Repertoire
|
|
186
204
|
# Returns the name of the id column to use for constructing bitset signatures
|
187
205
|
# over this model.
|
188
206
|
def faceting_id
|
189
|
-
[
|
207
|
+
[PACKED_SIGNATURE_COLUMN, DEFAULT_SIGNATURE_COLUMN].detect { |c| column_names.include?(c) }
|
190
208
|
end
|
191
209
|
|
192
210
|
def signature_wastage(col=nil)
|
@@ -194,9 +212,14 @@ module Repertoire
|
|
194
212
|
connection.signature_wastage(table_name, col)
|
195
213
|
end
|
196
214
|
|
197
|
-
def
|
198
|
-
|
215
|
+
def ensure_numbering(signature_column)
|
216
|
+
if signature_column == DEFAULT_SIGNATURE_COLUMN
|
217
|
+
connection.remove_column(table_name, PACKED_SIGNATURE_COLUMN) if column_names.include?(PACKED_SIGNATURE_COLUMN)
|
218
|
+
else
|
219
|
+
connection.renumber_table(table_name, PACKED_SIGNATURE_COLUMN, SIGNATURE_WASTAGE_THRESHOLD)
|
220
|
+
end
|
199
221
|
end
|
222
|
+
|
200
223
|
end
|
201
224
|
end
|
202
225
|
end
|
@@ -1,16 +1,19 @@
|
|
1
1
|
module Repertoire
|
2
2
|
module Faceting #:nodoc:
|
3
|
+
#
|
4
|
+
# Standard routing extensions for Repertoire Faceting webservices.
|
5
|
+
#
|
6
|
+
# Example::Application.routes.draw do
|
7
|
+
# faceting_for :paintings
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# N.B. Include faceting routes before any resources!
|
11
|
+
#
|
3
12
|
module Routing
|
4
13
|
|
5
14
|
#
|
6
15
|
# Add routes for the faceting webservices provided by the Controller mixin.
|
7
16
|
#
|
8
|
-
# Example::Application.routes.draw do
|
9
|
-
# faceting_for :nobelists
|
10
|
-
# end
|
11
|
-
#
|
12
|
-
# N.B. Include faceting routes before any resources!
|
13
|
-
#
|
14
17
|
def faceting_for(*controllers)
|
15
18
|
options = controllers.extract_options!
|
16
19
|
|
@@ -25,4 +28,3 @@ module Repertoire
|
|
25
28
|
end
|
26
29
|
end
|
27
30
|
end
|
28
|
-
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 5
|
8
|
-
-
|
9
|
-
version: 0.5.
|
8
|
+
- 3
|
9
|
+
version: 0.5.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Christopher York
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-11-03 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|