1 package OpenILS::Application::Storage::Publisher::metabib;
2 use base qw/OpenILS::Application::Storage/;
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;
11 use Digest::MD5 qw/md5_hex/;
13 my $log = 'OpenSRF::Utils::Logger';
24 my $term = $args{term};
25 my $limiters = $args{restrict};
26 my $limit = $args{limit} || 100;
27 my $offset = $args{offset} || 0;
30 my $cache_key = md5_hex(Dumper($limiters).$term);
32 my $cached_recs = OpenSRF::Utils::Cache->new->get_cache( $cache_key );
33 return [ @$cached_recs[$offset .. $limit - 1] ] if (defined $cached_recs);
35 my ($index_col) = metabib::full_rec->columns('FTS');
36 $index_col ||= 'value';
37 my $search_table = metabib::full_rec->table;
39 my $metabib_metarecord_source_map_table = metabib::metarecord_source_map->table;
40 my $asset_call_number_table = asset::call_number->table;
42 my $fts = OpenILS::Application::Storage::FTS->compile($term, 'value',"$index_col");
44 my $fts_where = $fts->sql_where_clause();
45 my @fts_ranks = $fts->fts_rank;
47 my $rank = join(' + ', @fts_ranks);
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);
56 my $where = join(' OR ', @wheres);
58 my $select = "SELECT record, sum($rank) FROM $search_table WHERE $where GROUP BY 1 ORDER BY 2 DESC;";
60 $log->debug("Search SQL :: [$select]",DEBUG);
62 my $recs = metabib::full_rec->db_Main->selectall_arrayref($select, {}, @binds);
63 $log->debug("Search yielded ".scalar(@$recs)." results.",DEBUG);
65 $client->respond_complete( [ @$recs[0 .. $window - 1] ] );
67 OpenSRF::Utils::Cache->new->put_cache( $cache_key => $recs );
72 __PACKAGE__->register_method(
73 api_name => 'open-ils.storage.direct.metabib.full_rec.search_fts.value',
74 method => 'search_full_rec',
78 __PACKAGE__->register_method(
79 api_name => 'open-ils.storage.direct.metabib.full_rec.search_fts.index_vector',
80 method => 'search_full_rec',
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 {
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;
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);
102 my $cached_recs = OpenSRF::Utils::Cache->new->get_cache( $cache_key );
103 return [ @$cached_recs[$offset .. $limit - 1] ] if (defined $cached_recs);
105 $log->debug("Cache key for $search_class search of '$term' at ($ou,$ou_type) will be $cache_key", DEBUG);
107 my $descendants = defined($ou_type) ?
108 "actor.org_unit_descendants($ou, $ou_type)" :
109 "actor.org_unit_descendants($ou)";
111 my $class = $self->{cdbi};
112 my $search_table = $class->table;
114 my $metabib_metarecord_source_map_table = metabib::metarecord_source_map->table;
115 my $asset_call_number_table = asset::call_number->table;
117 my ($index_col) = $class->columns('FTS');
118 $index_col ||= 'value';
120 my $fts = OpenILS::Application::Storage::FTS->compile($term, 'value', "$index_col");
122 my $fts_where = $fts->sql_where_clause;
123 my @fts_ranks = $fts->fts_rank;
125 my $rank = join(' + ', @fts_ranks);
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,
134 AND m.source = f.source
135 AND cn.record = m.source
136 AND cn.owning_lib = d.id
141 $log->debug("Field Search SQL :: [$select]",DEBUG);
143 my $recs = $class->db_Main->selectall_arrayref($select);
145 $log->debug("Search yielded ".scalar(@$recs)." results.",DEBUG);
147 $client->respond_complete( [ @$recs[$offset .. $limit - 1] ] );
149 OpenSRF::Utils::Cache->new->put_cache( $cache_key => $recs );
154 __PACKAGE__->register_method(
155 api_name => 'open-ils.storage.metabib.title.search_fts.metarecord',
156 method => 'search_class_fts',
159 cdbi => 'metabib::title_field_entry',
161 __PACKAGE__->register_method(
162 api_name => 'open-ils.storage.metabib.author.search_fts.metarecord',
163 method => 'search_class_fts',
166 cdbi => 'metabib::author_field_entry',
168 __PACKAGE__->register_method(
169 api_name => 'open-ils.storage.metabib.subject.search_fts.metarecord',
170 method => 'search_class_fts',
173 cdbi => 'metabib::subject_field_entry',
175 __PACKAGE__->register_method(
176 api_name => 'open-ils.storage.metabib.keyword.search_fts.metarecord',
177 method => 'search_class_fts',
180 cdbi => 'metabib::keyword_field_entry',
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 {
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;
195 my $descendants = defined($ou_type) ?
196 "actor.org_unit_descendants($ou, $ou_type)" :
197 "actor.org_unit_descendants($ou)";
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_');
203 my $cached_recs = OpenSRF::Utils::Cache->new->get_cache( $cache_key );
204 return $cached_recs if (defined $cached_recs);
206 my $class = $self->{cdbi};
207 my $search_table = $class->table;
209 my $metabib_metarecord_source_map_table = metabib::metarecord_source_map->table;
210 my $asset_call_number_table = asset::call_number->table;
212 my ($index_col) = $class->columns('FTS');
213 $index_col ||= 'value';
215 my $fts = OpenILS::Application::Storage::FTS->compile($term, 'value',"$index_col");
217 my $fts_where = $fts->sql_where_clause;
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,
227 AND m.source = f.source
228 AND cn.record = m.source
229 AND cn.owning_lib = d.id;
232 $log->debug("Field Search Count SQL :: [$select]",DEBUG);
234 my $recs = $class->db_Main->selectrow_arrayref($select)->[0];
236 $log->debug("Count Search yielded $recs results.",DEBUG);
238 OpenSRF::Utils::Cache->new->put_cache( $cache_key => $recs );
243 __PACKAGE__->register_method(
244 api_name => 'open-ils.storage.metabib.title.search_fts.metarecord_count',
245 method => 'search_class_fts_count',
248 cdbi => 'metabib::title_field_entry',
250 __PACKAGE__->register_method(
251 api_name => 'open-ils.storage.metabib.author.search_fts.metarecord_count',
252 method => 'search_class_fts_count',
255 cdbi => 'metabib::author_field_entry',
257 __PACKAGE__->register_method(
258 api_name => 'open-ils.storage.metabib.subject.search_fts.metarecord_count',
259 method => 'search_class_fts_count',
262 cdbi => 'metabib::subject_field_entry',
264 __PACKAGE__->register_method(
265 api_name => 'open-ils.storage.metabib.keyword.search_fts.metarecord_count',
266 method => 'search_class_fts_count',
269 cdbi => 'metabib::keyword_field_entry',