LP#1389403 Add normalizer detection to call number browse
authorDan Wells <dbw2@calvin.edu>
Fri, 4 Oct 2013 14:02:39 +0000 (10:02 -0400)
committerBen Shum <bshum@biblio.org>
Tue, 16 Dec 2014 19:52:57 +0000 (14:52 -0500)
When finding the pivot for call number browse, we currently rely on
simple label matching (rather than normalized label matching), since
we do not know at the time of the search which normalizer we should
use.

Rather than blindly using the label, let's select the pivot in two
phases.  First, we will do what we do know, getting as close as
possible by label alone.  If we find an exact match, we are done (same
as the current code).  If we don't find an exact match, we take the
normalizer setting from the closest label match, normalize our input,
then search again.

This method *greatly* improves the overall accuracy of call number
searching whenever the call number being browsed for does not exist,
while causing no harm to accuracy when it does exist (since it will
either match the label or normalize to the same call number anyway).

Eventually, we may want to add interface elements for selecting the
call number type, probably defaulting to the default call number type
for the org unit being searched, but even with that in place, this
"auto-detection" logic should still be valuable.

Signed-off-by: Dan Wells <dbw2@calvin.edu>
Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Signed-off-by: Ben Shum <bshum@biblio.org>
Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
Open-ILS/src/sql/Pg/040.schema.asset.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.function.cn_normalizers_immutable.sql [new file with mode: 0644]

index bf795e4..61e9c07 100644 (file)
@@ -339,15 +339,38 @@ sub _label_sortkey_from_label {
               deleted    => 'f',
               @$cp_filter
             },
-            { limit     => 1,
+            { flesh     => 1,
+              flesh_fields  => { acn => [qw/label_class/] },
+              limit     => 1,
               order_by  => { acn => "oils_text_as_bytea(label), id" }
             }
         )->gather(1);
     if (@$closest_cn) {
-        return $closest_cn->[0]->label_sortkey;
-    } else {
-        return '~~~'; #fallback to high ascii value, we are at the end
+        if ($closest_cn->[0]->label eq $label) {
+            # we found an exact match stop here
+            return $closest_cn->[0]->label_sortkey;
+        } else {
+            # we got as close as we could by label alone, let's try to
+            # normalize and get closer
+            $closest_cn = $_storage->request(
+                "open-ils.cstore.direct.asset.call_number.search.atomic",
+                { label_sortkey
+                             => { ">=" => [$closest_cn->[0]->label_class->normalizer, $label] },
+                  owning_lib => $ou_ids,
+                  deleted    => 'f',
+                  @$cp_filter
+                },
+                { limit     => 1,
+                  order_by  => { acn => "label_sortkey, id" }
+                }
+            )->gather(1);
+            if (@$closest_cn) {
+                return $closest_cn->[0]->label_sortkey;
+            }
+        }
     }
+
+    return '~~~'; #fallback to high ascii value, we are at the end of the range
 }
 
 sub cn_browse {
index 2381fdb..e7b1daa 100644 (file)
@@ -348,7 +348,7 @@ CREATE OR REPLACE FUNCTION asset.label_normalizer_generic(TEXT) RETURNS TEXT AS
     $callnum =~ s/ {2,}/ /g;
 
     return $callnum;
-$func$ LANGUAGE PLPERLU;
+$func$ LANGUAGE PLPERLU IMMUTABLE;
 
 CREATE OR REPLACE FUNCTION asset.label_normalizer_dewey(TEXT) RETURNS TEXT AS $func$
     # Derived from the Koha C4::ClassSortRoutine::Dewey module
@@ -387,7 +387,7 @@ CREATE OR REPLACE FUNCTION asset.label_normalizer_dewey(TEXT) RETURNS TEXT AS $f
 
     return $key;
 
-$func$ LANGUAGE PLPERLU;
+$func$ LANGUAGE PLPERLU IMMUTABLE;
 
 
 CREATE OR REPLACE FUNCTION asset.label_normalizer_lc(TEXT) RETURNS TEXT AS $func$
@@ -401,7 +401,7 @@ CREATE OR REPLACE FUNCTION asset.label_normalizer_lc(TEXT) RETURNS TEXT AS $func
     my $callnum = Library::CallNumber::LC->new(shift);
     return $callnum->normalize();
 
-$func$ LANGUAGE PLPERLU;
+$func$ LANGUAGE PLPERLU IMMUTABLE;
 
 INSERT INTO asset.call_number_class (name, normalizer, field) VALUES 
     ('Generic', 'asset.label_normalizer_generic', '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'),
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.function.cn_normalizers_immutable.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.function.cn_normalizers_immutable.sql
new file mode 100644 (file)
index 0000000..60618da
--- /dev/null
@@ -0,0 +1,9 @@
+BEGIN;
+
+--SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+ALTER FUNCTION asset.label_normalizer_generic(TEXT) IMMUTABLE;
+ALTER FUNCTION asset.label_normalizer_dewey(TEXT) IMMUTABLE;
+ALTER FUNCTION asset.label_normalizer_lc(TEXT) IMMUTABLE;
+
+COMMIT;