diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini
index a19f2bb2df27dbe3c67abeca87c0f6c26d5ecaa5..f0576f491e2b9b5ef9196c8da7bec2548936b828 100644
--- a/config/vufind/searches.ini
+++ b/config/vufind/searches.ini
@@ -136,10 +136,10 @@ relevance = sort_relevance
 year = sort_year
 year asc = "sort_year asc"
 
-; Use the "callnumber" line for LC or the "dewey-sort" line for Dewey Decimal.
+; Use the "callnumber-sort" line for LC or the "dewey-sort" line for Dewey Decimal.
 ; If you want to enable both systems for sorting, you can uncomment both lines,
 ; but you will need to add some custom text to distinguish between the two.
-callnumber = sort_callnumber
+callnumber-sort = sort_callnumber
 ;dewey-sort = sort_callnumber
 
 author = sort_author
diff --git a/config/vufind/searchspecs.yaml b/config/vufind/searchspecs.yaml
index e44e42f5c55f8fcbb4be295b56ddeb36c91c6698..ce45d0caf13cb70d14c91951634a5305d91f51ae 100644
--- a/config/vufind/searchspecs.yaml
+++ b/config/vufind/searchspecs.yaml
@@ -477,7 +477,7 @@ DeweyBrowse:
 
 LccBrowse:
   QueryFields:
-    callnumber-a:
+    callnumber-raw:
       - [onephrase, ~]
 
 CallNumber:
@@ -486,7 +486,6 @@ CallNumber:
   # which will return a larger number of hits at a lower boost.
   CustomMunge:
     callnumber_exact:
-      - [uppercase]
       # Strip whitespace and quotes:
       - [preg_replace, '/[ "]/', ""]
       # Escape colons (unescape first to avoid double-escapes):
@@ -495,7 +494,6 @@ CallNumber:
       # Strip pre-existing trailing asterisks:
       - [preg_replace, "/\*+$/", ""]
     callnumber_fuzzy:
-      - [uppercase]
       # Strip whitespace and quotes:
       - [preg_replace, '/[ "]/', ""]
       # Escape colons (unescape first to avoid double-escapes):
@@ -505,10 +503,10 @@ CallNumber:
       - [preg_replace, "/\*+$/", ""]
       - [append, "*"]
   QueryFields:
-    callnumber:
+    callnumber-search:
       - [callnumber_exact, 1000]
       - [callnumber_fuzzy, ~]
-    dewey-full:
+    dewey-search:
       - [callnumber_exact, 1000]
       - [callnumber_fuzzy, ~]
 
diff --git a/import/marc.properties b/import/marc.properties
index 27378ab43aedf7b131d3c8b9c066c2fb3e3672f8..9aa34aaed99fde7f0517457a5bb57203f85b482f 100644
--- a/import/marc.properties
+++ b/import/marc.properties
@@ -49,13 +49,11 @@ contents = 505a:505t
 isbn = 020a:773z
 issn = 022a:440x:490x:730x:773x:776x:780x:785x
 
-callnumber = custom, getFullCallNumber(099ab:090ab:050ab)
-callnumber-a = 099a:090a:050a, first
 callnumber-first = 099a[0]:090a[0]:050a[0], callnumber_map.properties, first
-callnumber-first-code = 099a[0]:090a[0]:050a[0], first
 callnumber-subject = custom, getCallNumberSubject(090a:050a), callnumber_subject_map.properties
-callnumber-subject-code = custom, getCallNumberSubject(090a:050a)
 callnumber-label = custom, getCallNumberLabel(090a:050a)
+callnumber-sort = custom, getLCSortable(099ab:090ab:050ab)
+callnumber-raw = 099ab:090ab:050ab
 
 topic = custom, getAllSubfields(600:610:611:630:650:653:656, " ")
 genre = custom, getAllSubfields(655, " ")
diff --git a/import/marc_local.properties b/import/marc_local.properties
index 7e064492b1ae4bd77ef173b10b973910627728f9..b29857e28b4af15763fb7e87b1bd15502c40216c 100644
--- a/import/marc_local.properties
+++ b/import/marc_local.properties
@@ -14,9 +14,7 @@
 # (by default, the scripts have the same behavior as the built-in functions,
 # but the external scripts are easier to customize to your needs).
 #format = script(format.bsh), getFormat, format_map.properties
-#callnumber = script(callnumber.bsh), getFullCallNumber(099ab:090ab:050ab)
 #callnumber-subject = script(callnumber.bsh), getCallNumberSubject(090a:050a), callnumber_subject_map.properties
-#callnumber-subject-code = script(callnumber.bsh), getCallNumberSubject(090a:050a)
 #callnumber-label = script(callnumber.bsh), getCallNumberLabel(090a:050a)
 #publishDate = script(getdate.bsh), getDate
 #illustrated = script(illustrated.bsh), isIllustrated
diff --git a/index-alphabetic-browse.bat b/index-alphabetic-browse.bat
index c7dd8d9346ba2e4f5afbf5acd7aecec64472271f..6c0eeb3dc5b976231ecd5651c7ba65478a2561f2 100644
--- a/index-alphabetic-browse.bat
+++ b/index-alphabetic-browse.bat
@@ -63,7 +63,7 @@ call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse hierarchy hierarchy_
 call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse title title_fullStr 1 "-Dbibleech=StoredFieldLeech -Dsortfield=title_sort -Dvaluefield=title_fullStr"
 call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse topic topic_browse
 call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse author author_browse
-call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse lcc callnumber-a 1 "-Dbrowse.normalizer=org.vufind.util.LCCallNormalizer"
+call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse lcc callnumber-raw 1 "-Dbrowse.normalizer=org.vufind.util.LCCallNormalizer"
 call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse dewey dewey-raw 1 "-Dbrowse.normalizer=org.vufind.util.DeweyCallNormalizer"
 goto end
 
diff --git a/index-alphabetic-browse.sh b/index-alphabetic-browse.sh
index 58d28d36e57bcd76d6eb4001abad062a87b52d3a..60ff54234e25f676f7954c34798e17b8ed5bec2f 100755
--- a/index-alphabetic-browse.sh
+++ b/index-alphabetic-browse.sh
@@ -70,5 +70,5 @@ build_browse "hierarchy" "hierarchy_browse"
 build_browse "title" "title_fullStr" 1 "-Dbibleech=StoredFieldLeech -Dsortfield=title_sort -Dvaluefield=title_fullStr"
 build_browse "topic" "topic_browse"
 build_browse "author" "author_browse"
-build_browse "lcc" "callnumber-a" 1 "-Dbrowse.normalizer=org.vufind.util.LCCallNormalizer"
+build_browse "lcc" "callnumber-raw" 1 "-Dbrowse.normalizer=org.vufind.util.LCCallNormalizer"
 build_browse "dewey" "dewey-raw" 1 "-Dbrowse.normalizer=org.vufind.util.DeweyCallNormalizer"
diff --git a/module/VuFind/src/VuFind/Autocomplete/SolrCN.php b/module/VuFind/src/VuFind/Autocomplete/SolrCN.php
index c56fa796b8de41f6918c38285a6401a1f91a0504..40169516611e1d23a937f56011849f8ddd8c8e1d 100644
--- a/module/VuFind/src/VuFind/Autocomplete/SolrCN.php
+++ b/module/VuFind/src/VuFind/Autocomplete/SolrCN.php
@@ -72,11 +72,11 @@ class SolrCN extends Solr
         // first character is a number, give Dewey priority; otherwise, give
         // LC priority:
         if (is_numeric(substr(trim($query), 0, 1))) {
-            $this->setDisplayField(['dewey-full', 'callnumber-a']);
-            $this->setSortField("dewey-sort,callnumber");
+            $this->setDisplayField(['dewey-full', 'callnumber-raw']);
+            $this->setSortField("dewey-sort,callnumber-sort");
         } else {
-            $this->setDisplayField(['callnumber-a', 'dewey-full']);
-            $this->setSortField("callnumber,dewey-sort");
+            $this->setDisplayField(['callnumber-raw', 'dewey-full']);
+            $this->setSortField("callnumber-sort,dewey-sort");
         }
 
         return $query;
diff --git a/module/VuFind/src/VuFind/RecordDriver/EIT.php b/module/VuFind/src/VuFind/RecordDriver/EIT.php
index 99c601d5b1f60ce66186ecd76e8a789f1e79f3ba..7c2ee6bd32196a97564517054e97aeb64e2c877c 100644
--- a/module/VuFind/src/VuFind/RecordDriver/EIT.php
+++ b/module/VuFind/src/VuFind/RecordDriver/EIT.php
@@ -112,13 +112,13 @@ class EIT extends SolrDefault
     }
 
     /**
-     * Get the call number associated with the record (empty string if none).
+     * Get the call numbers associated with the record (empty string if none).
      *
-     * @return string
+     * @return array
      */
-    public function getCallNumber()
+    public function getCallNumbers()
     {
-        return "";
+        return [];
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
index e0347a3ec854b3d83039b2edd8722e66f3274b2a..8454075c4f3a4c4e2f5ab9e3d86309f7407d4cec 100644
--- a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
+++ b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
@@ -266,18 +266,26 @@ class SolrDefault extends AbstractBase
     }
 
     /**
-     * Get the call number associated with the record (empty string if none).
+     * Get the first call number associated with the record (empty string if none).
      *
      * @return string
      */
     public function getCallNumber()
     {
-        // Use the callnumber-a field from the Solr index; the plain callnumber
-        // field is normalized to have no spaces, so it is unsuitable for display.
-        return isset($this->fields['callnumber-a']) ?
-            $this->fields['callnumber-a'] : '';
+        $all = $this->getCallNumbers();
+        return isset($all[0]) ? $all[0] : '';
     }
 
+    /**
+     * Get all call numbers associated with the record (empty string if none).
+     *
+     * @return array
+     */
+    public function getCallNumbers()
+    {
+        return isset($this->fields['callnumber-raw'])
+            ? $this->fields['callnumber-raw'] : [];
+    }
     /**
      * Return the first valid ISBN found in the record (favoring ISBN-10 over
      * ISBN-13 when possible).
diff --git a/module/VuFind/src/VuFind/RecordDriver/Summon.php b/module/VuFind/src/VuFind/RecordDriver/Summon.php
index ff61954a91d6f16c03f0d8cfa940279c9f65be9c..7eb20571b52c0a5ec041c1f76e163272bfd394ec 100644
--- a/module/VuFind/src/VuFind/RecordDriver/Summon.php
+++ b/module/VuFind/src/VuFind/RecordDriver/Summon.php
@@ -92,15 +92,16 @@ class Summon extends SolrDefault
     }
 
     /**
-     * Get the call number associated with the record (empty string if none).
+     * Get the call numbers associated with the record (empty string if none).
      *
-     * @return string
+     * @return array
      */
-    public function getCallNumber()
+    public function getCallNumbers()
     {
         // Summon calls this LCCNum even though it may be Dewey
-        return isset($this->fields['LCCCallnum']) ?
-            $this->fields['LCCCallnum'] : '';
+        return isset($this->fields['LCCCallnum'])
+            && !empty($this->fields['LCCCallnum'])
+            ? [$this->fields['LCCCallnum']] : [];
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/RecordDriver/WorldCat.php b/module/VuFind/src/VuFind/RecordDriver/WorldCat.php
index e923b9c40918885998d9abfc84dc2bb6c155d844..bfe57c6d7fe756e92c924786fdb04743c4eb3f24 100644
--- a/module/VuFind/src/VuFind/RecordDriver/WorldCat.php
+++ b/module/VuFind/src/VuFind/RecordDriver/WorldCat.php
@@ -152,18 +152,23 @@ class WorldCat extends SolrMarc
     }
 
     /**
-     * Get the call number associated with the record (empty string if none).
-     * If both LC and Dewey call numbers exist, LC will be favored.
+     * Get the call numbers associated with the record (empty string if none).
      *
-     * @return string
+     * @return array
      */
-    public function getCallNumber()
+    public function getCallNumbers()
     {
-        $callNo = $this->getFirstFieldValue('090', ['a', 'b']);
-        if (empty($callNo)) {
-            $callNo = $this->getFirstFieldValue('050', ['a', 'b']);
+        $retVal = [];
+        foreach (['090', '050'] as $field) {
+            $callNo = $this->getFirstFieldValue($field, ['a', 'b']);
+            if (!empty($callNo)) {
+                $retVal[] = $callNo;
+            }
+        }
+        if (!empty($dewey = $this->getDeweyCallNumber())) {
+            $retVal[] = $dewey;
         }
-        return empty($callNo) ? $this->getDeweyCallNumber() : $callNo;
+        return $retVal;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Search/Solr/Options.php b/module/VuFind/src/VuFind/Search/Solr/Options.php
index e9bc34b3847767836b1a694a0ccd7a879a23a7dc..c851c81aa3083f2d5407f759082096cffa5c8cd4 100644
--- a/module/VuFind/src/VuFind/Search/Solr/Options.php
+++ b/module/VuFind/src/VuFind/Search/Solr/Options.php
@@ -121,7 +121,7 @@ class Options extends \VuFind\Search\Base\Options
         } else {
             $this->sortOptions = ['relevance' => 'sort_relevance',
                 'year' => 'sort_year', 'year asc' => 'sort_year asc',
-                'callnumber' => 'sort_callnumber', 'author' => 'sort_author',
+                'callnumber-sort' => 'sort_callnumber', 'author' => 'sort_author',
                 'title' => 'sort_title'];
         }
         // Load view preferences (or defaults if none in .ini file):
diff --git a/module/VuFind/src/VuFind/Search/Solr/Params.php b/module/VuFind/src/VuFind/Search/Solr/Params.php
index 64ec0c036ea47af5a08c7917edcd718ecc3d8b0d..d1580544f60c846ad19ab92706fc24dc0dc14cd2 100644
--- a/module/VuFind/src/VuFind/Search/Solr/Params.php
+++ b/module/VuFind/src/VuFind/Search/Solr/Params.php
@@ -397,12 +397,11 @@ class Params extends \VuFind\Search\Base\Params
     {
         static $table = [
             'year' => ['field' => 'publishDateSort', 'order' => 'desc'],
-            'publishDateSort' =>
-                ['field' => 'publishDateSort', 'order' => 'desc'],
+            'publishDateSort' => ['field' => 'publishDateSort', 'order' => 'desc'],
             'author' => ['field' => 'authorStr', 'order' => 'asc'],
             'title' => ['field' => 'title_sort', 'order' => 'asc'],
             'relevance' => ['field' => 'score', 'order' => 'desc'],
-            'callnumber' => ['field' => 'callnumber', 'order' => 'asc'],
+            'callnumber' => ['field' => 'callnumber-sort', 'order' => 'asc'],
         ];
         $normalized = [];
         foreach (explode(',', $sort) as $component) {
diff --git a/solr/biblio/conf/schema.xml b/solr/biblio/conf/schema.xml
index cca59e05fa7a40b89aa43966a4b539e98d68b177..23fb678c42b3399b8f3f3eda8c44345ee07b880f 100644
--- a/solr/biblio/conf/schema.xml
+++ b/solr/biblio/conf/schema.xml
@@ -93,6 +93,14 @@
         <filter class="solr.LengthFilterFactory" min="1" max="100" />
       </analyzer>
     </fieldType>
+    <!-- case-insensitive/whitespace-agnostic field type for callnumber searching -->
+    <fieldType name="callnumberSearch" class="solr.TextField" sortMissingLast="true" omitNorms="true">
+      <analyzer>
+        <charFilter class="solr.PatternReplaceCharFilterFactory" pattern="(\s)" replacement=""/>
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <filter class="solr.ICUFoldingFilterFactory"/>
+      </analyzer>
+    </fieldType>
     <fieldType name="date" class="solr.TrieDateField" sortMissingLast="true" omitNorms="true" precisionStep="6"/>
     <fieldType name="random" class="solr.RandomSortField" indexed="true" />
     <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
@@ -144,19 +152,19 @@
    <field name="isbn" type="isn" indexed="true" stored="true" multiValued="true"/>
    <field name="issn" type="isn" indexed="true" stored="true" multiValued="true"/>
    <field name="oclc_num" type="string" indexed="true" stored="true" multiValued="true" />
-   <field name="callnumber" type="string" indexed="true" stored="true"/>
-   <field name="callnumber-a" type="string" indexed="true" stored="true"/>
    <field name="callnumber-first" type="string" indexed="true" stored="true"/>
-   <field name="callnumber-first-code" type="string" indexed="true" stored="true"/>
    <field name="callnumber-subject" type="string" indexed="true" stored="true"/>
-   <field name="callnumber-subject-code" type="string" indexed="true" stored="true"/>
    <field name="callnumber-label" type="string" indexed="true" stored="true"/>
+   <field name="callnumber-sort" type="string" indexed="true" stored="true"/>
+   <field name="callnumber-raw" type="string" indexed="true" stored="true" multiValued="true" />
+   <field name="callnumber-search" type="callnumberSearch" indexed="true" stored="true" multiValued="true" />
    <field name="dewey-hundreds" type="string" indexed="true" stored="true" multiValued="true"/>
    <field name="dewey-tens" type="string" indexed="true" stored="true" multiValued="true"/>
    <field name="dewey-ones" type="string" indexed="true" stored="true" multiValued="true"/>
    <field name="dewey-full" type="string" indexed="true" stored="true" multiValued="true"/>
    <field name="dewey-sort" type="string" indexed="true" stored="true" />
    <field name="dewey-raw" type="string" indexed="true" stored="true" multiValued="true" />
+   <field name="dewey-search" type="callnumberSearch" indexed="true" stored="true" multiValued="true" />
    <field name="author2" type="textProper" indexed="true" stored="true" multiValued="true"/>
    <field name="author2Str" type="string" indexed="true" stored="true" multiValued="true"/>
    <field name="author2-role" type="string" indexed="true" stored="true" multiValued="true"/>
@@ -248,6 +256,9 @@
  <!-- CopyFields for All Fields -->
  <copyField source="format"    dest="allfields"/>
  <copyField source="format"    dest="allfields_unstemmed"/>
+ <!-- CopyFields for call numbers -->
+ <copyField source="dewey-raw" dest="dewey-search"/>
+ <copyField source="callnumber-raw" dest="callnumber-search"/>
  <!-- Default Boolean Operator -->
  <solrQueryParser defaultOperator="AND"/>
 </schema>
diff --git a/solr/biblio/conf/solrconfig.xml b/solr/biblio/conf/solrconfig.xml
index aa5c35a49c486623ea09a8527a01d680bf3b8546..fa2f8dd7689ddb4210fd543909c093efc3218227 100644
--- a/solr/biblio/conf/solrconfig.xml
+++ b/solr/biblio/conf/solrconfig.xml
@@ -453,7 +453,7 @@
 
     <lst name="lcc">
       <str name="DBpath">${solr.solr.home:./solr}/alphabetical_browse/lcc_browse.db</str>
-      <str name="field">callnumber-a</str>
+      <str name="field">callnumber-raw</str>
       <str name="normalizer">org.vufind.util.LCCallNormalizer</str>
     </lst>