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