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