]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm
removing unused fields andd adding paged caching
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / Publisher / metabib.pm
1 package OpenILS::Application::Storage::Publisher::metabib;
2 use base qw/OpenILS::Application::Storage::Publisher/;
3 use vars qw/$VERSION/;
4 use OpenSRF::EX qw/:try/;
5 use OpenILS::Application::Storage::FTS;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenSRF::Utils::Logger qw/:level/;
8 use OpenSRF::Utils::Cache;
9 use Data::Dumper;
10 use Digest::MD5 qw/md5_hex/;
11
12 my $log = 'OpenSRF::Utils::Logger';
13
14 $VERSION = 1;
15
16 sub metarecord_copy_count {
17         my $self = shift;
18         my $client = shift;
19
20         my %args = @_;
21
22         my $sm_table = metabib::metarecord_source_map->table;
23         my $cn_table = asset::call_number->table;
24         my $cp_table = asset::copy->table;
25         my $out_table = actor::org_unit_type->table;
26         my $descendants = "actor.org_unit_descendants(u.id)";
27         my $ancestors = "actor.org_unit_ancestors(?)";
28
29         my $sql = <<"   SQL";
30                 SELECT  t.depth,
31                         u.id AS org_unit,
32                         sum(
33                                 (SELECT count(cp.id)
34                                   FROM  $sm_table r
35                                         JOIN $cn_table cn ON (cn.record = r.source)
36                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
37                                         JOIN $descendants a ON (cp.circ_lib = a.id)
38                                   WHERE r.metarecord = ?
39                                         AND cp.opac_visible IS TRUE)
40                         ) AS count,
41                         sum(
42                                 (SELECT count(cp.id)
43                                   FROM  $sm_table r
44                                         JOIN $cn_table cn ON (cn.record = r.source)
45                                         JOIN $cp_table cp ON (cn.id = cp.call_number)
46                                         JOIN $descendants a ON (cp.circ_lib = a.id)
47                                   WHERE r.metarecord = ?
48                                         AND cp.status = 0
49                                         AND cp.opac_visible IS TRUE)
50                         ) AS available
51
52                   FROM  $ancestors u
53                         JOIN $out_table t ON (u.ou_type = t.id)
54                   GROUP BY 1,2
55         SQL
56
57         my $sth = metabib::metarecord_source_map->db_Main->prepare_cached($sql);
58         $sth->execute(''.$args{metarecord}, ''.$args{metarecord}, ''.$args{org_unit});
59         while ( my $row = $sth->fetchrow_hashref ) {
60                 $client->respond( $row );
61         }
62         return undef;
63 }
64 __PACKAGE__->register_method(
65         api_name        => 'open-ils.storage.metabib.metarecord.copy_count',
66         method          => 'metarecord_copy_count',
67         api_level       => 1,
68         stream          => 1,
69         cachable        => 1,
70 );
71
72 sub search_full_rec {
73         my $self = shift;
74         my $client = shift;
75
76         my %args = @_;
77         
78         my $term = $args{term};
79         my $limiters = $args{restrict};
80
81         my ($index_col) = metabib::full_rec->columns('FTS');
82         $index_col ||= 'value';
83         my $search_table = metabib::full_rec->table;
84
85         my $fts = OpenILS::Application::Storage::FTS->compile($term, 'value',"$index_col");
86
87         my $fts_where = $fts->sql_where_clause();
88         my @fts_ranks = $fts->fts_rank;
89
90         my $rank = join(' + ', @fts_ranks);
91
92         my @binds;
93         my @wheres;
94         for my $limit (@$limiters) {
95                 push @wheres, "( tag = ? AND subfield LIKE ? AND $fts_where )";
96                 push @binds, $$limit{tag}, $$limit{subfield};
97                 $log->debug("Limiting query using { tag => $$limit{tag}, subfield => $$limit{subfield} }", DEBUG);
98         }
99         my $where = join(' OR ', @wheres);
100
101         my $select = "SELECT record, sum($rank) FROM $search_table WHERE $where GROUP BY 1 ORDER BY 2 DESC;";
102
103         $log->debug("Search SQL :: [$select]",DEBUG);
104
105         my $recs = metabib::full_rec->db_Main->selectall_arrayref($select, {}, @binds);
106         $log->debug("Search yielded ".scalar(@$recs)." results.",DEBUG);
107
108         $client->respond($_) for (@$recs);
109         return undef;
110 }
111 __PACKAGE__->register_method(
112         api_name        => 'open-ils.storage.direct.metabib.full_rec.search_fts.value',
113         method          => 'search_full_rec',
114         api_level       => 1,
115         stream          => 1,
116         cachable        => 1,
117 );
118 __PACKAGE__->register_method(
119         api_name        => 'open-ils.storage.direct.metabib.full_rec.search_fts.index_vector',
120         method          => 'search_full_rec',
121         api_level       => 1,
122         stream          => 1,
123         cachable        => 1,
124 );
125
126
127 # XXX factored most of the PG dependant stuff out of here... need to find a way to do "dependants".
128 sub search_class_fts {
129         my $self = shift;
130         my $client = shift;
131         my %args = @_;
132         
133         my $term = $args{term};
134         my $ou = $args{org_unit};
135         my $ou_type = $args{depth};
136
137
138         my $descendants = defined($ou_type) ?
139                                 "actor.org_unit_descendants($ou, $ou_type)" :
140                                 "actor.org_unit_descendants($ou)";
141
142         my $class = $self->{cdbi};
143         my $search_table = $class->table;
144
145         my $metabib_metarecord_source_map_table = metabib::metarecord_source_map->table;
146         my $asset_call_number_table = asset::call_number->table;
147         my $asset_copy_table = asset::copy->table;
148
149         my ($index_col) = $class->columns('FTS');
150         $index_col ||= 'value';
151
152         my $fts = OpenILS::Application::Storage::FTS->compile($term, 'value', "$index_col");
153
154         my $fts_where = $fts->sql_where_clause;
155         my @fts_ranks = $fts->fts_rank;
156
157         my $rank = join(' + ', @fts_ranks);
158
159         my $select = <<"        SQL";
160                 SELECT  m.metarecord, sum($rank)/count(m.source), count(DISTINCT cp.id)
161                   FROM  $search_table f,
162                         $metabib_metarecord_source_map_table m,
163                         $asset_call_number_table cn,
164                         $asset_copy_table cp,
165                         $descendants d
166                   WHERE $fts_where
167                         AND m.source = f.source
168                         AND cn.record = m.source
169                         AND cn.owning_lib = d.id
170                         AND cp.call_number = cn.id
171                         AND cp.opac_visible IS TRUE
172                   GROUP BY 1
173                   HAVING count(DISTINCT cp.id) > 0
174                   ORDER BY 2 DESC;
175         SQL
176
177         $log->debug("Field Search SQL :: [$select]",DEBUG);
178
179         my $recs = $class->db_Main->selectall_arrayref($select);
180         
181         $log->debug("Search yielded ".scalar(@$recs)." results.",DEBUG);
182
183         $client->respond($_) for (@$recs);
184         return undef;
185 }
186 __PACKAGE__->register_method(
187         api_name        => 'open-ils.storage.metabib.title.search_fts.metarecord',
188         method          => 'search_class_fts',
189         api_level       => 1,
190         stream          => 1,
191         cdbi            => 'metabib::title_field_entry',
192         cachable        => 1,
193 );
194 __PACKAGE__->register_method(
195         api_name        => 'open-ils.storage.metabib.author.search_fts.metarecord',
196         method          => 'search_class_fts',
197         api_level       => 1,
198         stream          => 1,
199         cdbi            => 'metabib::author_field_entry',
200         cachable        => 1,
201 );
202 __PACKAGE__->register_method(
203         api_name        => 'open-ils.storage.metabib.subject.search_fts.metarecord',
204         method          => 'search_class_fts',
205         api_level       => 1,
206         stream          => 1,
207         cdbi            => 'metabib::subject_field_entry',
208         cachable        => 1,
209 );
210 __PACKAGE__->register_method(
211         api_name        => 'open-ils.storage.metabib.keyword.search_fts.metarecord',
212         method          => 'search_class_fts',
213         api_level       => 1,
214         stream          => 1,
215         cdbi            => 'metabib::keyword_field_entry',
216         cachable        => 1,
217 );
218
219 # XXX factored most of the PG dependant stuff out of here... need to find a way to do "dependants".
220 sub search_class_fts_count {
221         my $self = shift;
222         my $client = shift;
223         my %args = @_;
224         
225         my $term = $args{term};
226         my $ou = $args{org_unit};
227         my $ou_type = $args{depth};
228         my $limit = $args{limit} || 100;
229         my $offset = $args{offset} || 0;
230
231         my $descendants = defined($ou_type) ?
232                                 "actor.org_unit_descendants($ou, $ou_type)" :
233                                 "actor.org_unit_descendants($ou)";
234                 
235
236         (my $search_class = $self->api_name) =~ s/.*metabib.(\w+).search_fts.*/$1/o;
237         my $cache_key = md5_hex($search_class.$term.$ou.$ou_type.'_COUNT_');
238
239         my $cached_recs = OpenSRF::Utils::Cache->new->get_cache( $cache_key );
240         return $cached_recs if (defined $cached_recs);
241
242         my $class = $self->{cdbi};
243         my $search_table = $class->table;
244
245         my $metabib_metarecord_source_map_table = metabib::metarecord_source_map->table;
246         my $asset_call_number_table = asset::call_number->table;
247         my $asset_copy_table = asset::copy->table;
248
249         my ($index_col) = $class->columns('FTS');
250         $index_col ||= 'value';
251
252         my $fts = OpenILS::Application::Storage::FTS->compile($term, 'value',"$index_col");
253
254         my $fts_where = $fts->sql_where_clause;
255
256         # XXX test an "EXISTS version of descendant checking...
257         my $select = <<"        SQL";
258                 SELECT  count(distinct  m.metarecord)
259                   FROM  $search_table f,
260                         $metabib_metarecord_source_map_table m,
261                         $asset_call_number_table cn,
262                         $asset_copy_table cp,
263                         $descendants d
264                   WHERE $fts_where
265                         AND m.source = f.source
266                         AND cn.record = m.source
267                         AND cn.owning_lib = d.id
268                         AND cp.call_number = cn.id
269                         AND cp.opac_visible IS TRUE
270         SQL
271
272         $log->debug("Field Search Count SQL :: [$select]",DEBUG);
273
274         my $recs = $class->db_Main->selectrow_arrayref($select)->[0];
275         
276         $log->debug("Count Search yielded $recs results.",DEBUG);
277
278         OpenSRF::Utils::Cache->new->put_cache( $cache_key => $recs );
279
280         return $recs;
281
282 }
283 __PACKAGE__->register_method(
284         api_name        => 'open-ils.storage.metabib.title.search_fts.metarecord_count',
285         method          => 'search_class_fts_count',
286         api_level       => 1,
287         stream          => 1,
288         cdbi            => 'metabib::title_field_entry',
289         cachable        => 1,
290 );
291 __PACKAGE__->register_method(
292         api_name        => 'open-ils.storage.metabib.author.search_fts.metarecord_count',
293         method          => 'search_class_fts_count',
294         api_level       => 1,
295         stream          => 1,
296         cdbi            => 'metabib::author_field_entry',
297         cachable        => 1,
298 );
299 __PACKAGE__->register_method(
300         api_name        => 'open-ils.storage.metabib.subject.search_fts.metarecord_count',
301         method          => 'search_class_fts_count',
302         api_level       => 1,
303         stream          => 1,
304         cdbi            => 'metabib::subject_field_entry',
305         cachable        => 1,
306 );
307 __PACKAGE__->register_method(
308         api_name        => 'open-ils.storage.metabib.keyword.search_fts.metarecord_count',
309         method          => 'search_class_fts_count',
310         api_level       => 1,
311         stream          => 1,
312         cdbi            => 'metabib::keyword_field_entry',
313         cachable        => 1,
314 );
315
316 1;