[open-ils-commits] r8892 - trunk/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher

svn at svn.open-ils.org svn at svn.open-ils.org
Thu Mar 6 23:37:54 EST 2008


Author: miker
Date: 2008-03-06 23:05:19 -0500 (Thu, 06 Mar 2008)
New Revision: 8892

Modified:
   trunk/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm
Log:
shiny new search method based on staged search stored proc

Modified: trunk/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm
===================================================================
--- trunk/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm	2008-03-07 02:58:33 UTC (rev 8891)
+++ trunk/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm	2008-03-07 04:05:19 UTC (rev 8892)
@@ -1915,10 +1915,6 @@
 		$ou = actor::org_unit->search( { parent_ou => undef } )->next->id;
 	}
 
-	if (!defined($args{org_unit})) {
-		die "No target organizational unit passed to ".$self->api_name;
-	}
-
 	if (! scalar( keys %{$args{searches}} )) {
 		die "No search arguments were passed to ".$self->api_name;
 	}
@@ -2309,6 +2305,216 @@
 	cachable	=> 1,
 );
 
+# XXX factored most of the PG dependant stuff out of here... need to find a way to do "dependants".
+sub staged_fts {
+	my $self = shift;
+	my $client = shift;
+	my %args = @_;
+	
+	my $ou = $args{org_unit};
+	my $pref_lang = $args{prefered_language} || 'eng'; # XXX not used currently
+	my $limit = $args{limit} || 10;
+	my $offset = $args{offset} || 0;
+
+	if (!$ou) {
+		$ou = actor::org_unit->search( { parent_ou => undef } )->next->id;
+	}
+
+	if (! scalar( keys %{$args{searches}} )) {
+		die "No search arguments were passed to ".$self->api_name;
+	}
+
+	my (@statuses, at types, at forms, at lang, at aud, at lit_form, at vformats);
+
+	if ($args{available}) {
+		@statuses = (0,7);
+	}
+
+	if (my $s = $args{statuses}) {
+		$s = [$s] if (!ref($s));
+		@statuses = @$s;
+	}
+
+	if (my $a = $args{audience}) {
+		$a = [$a] if (!ref($a));
+		@aud = @$a;
+	}
+
+	if (my $l = $args{language}) {
+		$l = [$l] if (!ref($l));
+		@lang = @$l;
+	}
+
+	if (my $f = $args{lit_form}) {
+		$f = [$f] if (!ref($f));
+		@lit_form = @$f;
+	}
+
+	if (my $f = $args{item_form}) {
+		$f = [$f] if (!ref($f));
+		@forms = @$f;
+	}
+
+	if (my $t = $args{item_type}) {
+		$t = [$t] if (!ref($t));
+		@types = @$t;
+	}
+
+	if (my $v = $args{vr_format}) {
+		$v = [$v] if (!ref($v));
+		@vformats = @$v;
+	}
+
+	# XXX legacy format and item type support
+	if ($args{format}) {
+		my ($t, $f) = split '-', $args{format};
+		@types = split '', $t;
+		@forms = split '', $f;
+	}
+
+    my %stored_proc_search_args;
+	for my $search_group (sort keys %{$args{searches}}) {
+		(my $search_group_name = $search_group) =~ s/\|/_/gso;
+		my ($search_class,$search_field) = split /\|/, $search_group;
+		$log->debug("Searching class [$search_class] and field [$search_field]",DEBUG);
+
+		if ($search_field) {
+			unless ( config::metabib_field->search( field_class => $search_class, name => $search_field )->next ) {
+				$log->warn("Requested class [$search_class] or field [$search_field] does not exist!");
+				return undef;
+			}
+		}
+
+		my $class = $_cdbi->{$search_class};
+		my $search_table = $class->table;
+
+		my ($index_col) = $class->columns('FTS');
+		$index_col ||= 'value';
+
+		
+		my $fts = OpenILS::Application::Storage::FTS->compile(
+            $search_class => $args{searches}{$search_group}{term},
+            $search_group_name.'.value',
+            "$search_group_name.$index_col"
+        );
+		$fts->sql_where_clause; # this builds the ranks for us
+
+		my @fts_ranks = $fts->fts_rank;
+		my @fts_queries = $fts->fts_query;
+		my @phrases = map { lc($_) } $fts->phrases;
+		my @words = map { lc($_) } $fts->words;
+
+        $stored_proc_search_args{$search_group} = {
+            fts_rank    => \@fts_ranks,
+            fts_query   => \@fts_query,
+            phrase      => \@phrases,
+            word        => \@words,
+        };
+
+	}
+
+	my $param_search_ou = $ou;
+	my $param_depth = $args{depth}; $param_depth ||= 'NULL'
+    my $param_searches = OpenSRF::Utils::JSON->perl2JSON( \%stored_proc_search_args ); $param_searches =~ s/\$//go; $param_searches = '$$'.$param_searches.'$$';
+    my $param_statuses = '$${' . join(',', map { s/\$//go } @statuses) . '}$$';
+    my $param_audience = '$${' . join(',', map { s/\$//go } @aud) . '}$$';
+    my $param_language = '$${' . join(',', map { s/\$//go } @lang) . '}$$';
+    my $param_lit_form = '$${' . join(',', map { s/\$//go } @lit_form) . '}$$';
+    my $param_types = '$${' . join(',', map { s/\$//go } @types) . '}$$';
+    my $param_forms = '$${' . join(',', map { s/\$//go } @forms) . '}$$';
+    my $param_vformats = '$${' . join(',', map { s/\$//go } @vformats) . '}$$';
+	my $param_sort = $args{'sort'}; $param_sort =~ s/\$//go; $param_sort = '$$'.$param_sort.'$$';
+	my $param_sort_desc = (defined($args{sort_dir}) && $args{sort_dir} =~ /^d/io ? "'t'" : "'f'");
+	my $metarecord = ($self->api_name =~ /metabib/o) ? "'t'" : "'f'");
+	my $staff = ($self->api_name =~ /staff/o) ? "'t'" : "'f'");
+    my $param_rel_limit = $args{core_limit}; $param_rel_limit ||= 'NULL';
+    my $param_chk_limit = $args{check_limit}; $param_chk_limit ||= 'NULL';
+    my $param_skip_chk = $args{skip_check}; $param_skip_chk ||= 'NULL';
+
+	my $sth = metabib::metarecord_source_map->db_Main->prepare(<<"    SQL");
+        SELECT  *
+          FROM  search.staged_fts(
+                    $param_search_ou,
+                    $param_depth,
+                    $param_searches,
+                    $param_statuses,
+                    $param_audience,
+                    $param_language,
+                    $param_lit_form,
+                    $param_types,
+                    $param_forms,
+                    $param_vformats,
+                    $param_sort,
+                    $param_sort_desc,
+                    $metarecord,
+                    $staff,
+                    $param_rel_limit,
+                    $param_chk_limit,
+                    $param_skip_chk
+                );
+    SQL
+
+    my $recs = $sth->fetchall_arrayref({});
+    my $summary_row = pop @$recs;
+
+    my $total = $$summary_row{total};
+    my $checked = $$summary_row{checked};
+    my $visible = $$summary_row{visible};
+    my $deleted = $$summary_row{deleted};
+    my $excluded = $$summary_row{excluded};
+
+    my $estimate = $visible;
+    if ( $total > $checked ) {
+        my $deleted_ratio = $deleted / $checked;
+        my $exclution_ratio = $excluded / $checked;
+        my $delete_adjusted_total = $total - ( $total * $deleted_ratio );
+
+        $estimate = $$summary_row{estimated_hit_count} = int($delete_adjusted_total - ( $delete_adjusted_total * $exclution_ratio ));
+    }
+
+    delete $$summary_row{id};
+    delete $$summary_row{rel};
+    delete $$summary_row{record};
+
+    $client->respond( $summary_row );
+
+	$log->debug("Search yielded ".scalar(@$recs)." checked, visible results with an approximate visible total of $estimate.",DEBUG);
+
+	for my $rec (@$recs[$offset .. $offset + $limit - 1]) {
+		$client->respond( $rec );
+	}
+	return undef;
+}
+__PACKAGE__->register_method(
+	api_name	=> "open-ils.storage.biblio.multiclass.staged.search_fts",
+	method		=> 'staged_fts',
+	api_level	=> 1,
+	stream		=> 1,
+	cachable	=> 1,
+);
+__PACKAGE__->register_method(
+	api_name	=> "open-ils.storage.biblio.multiclass.staged.search_fts.staff",
+	method		=> 'staged_fts',
+	api_level	=> 1,
+	stream		=> 1,
+	cachable	=> 1,
+);
+__PACKAGE__->register_method(
+	api_name	=> "open-ils.storage.metabib.multiclass.staged.search_fts",
+	method		=> 'staged_fts',
+	api_level	=> 1,
+	stream		=> 1,
+	cachable	=> 1,
+);
+__PACKAGE__->register_method(
+	api_name	=> "open-ils.storage.metabib.multiclass.staged.search_fts.staff",
+	method		=> 'staged_fts',
+	api_level	=> 1,
+	stream		=> 1,
+	cachable	=> 1,
+);
+
+
 sub xref_count {
 	my $self = shift;
 	my $client = shift;



More information about the open-ils-commits mailing list