MDL-60759 search_solr: Solr 7+ compatibility
authorDavid Monllao <davidm@moodle.com>
Fri, 17 Nov 2017 11:10:06 +0000 (12:10 +0100)
committerDavid Monllao <davidm@moodle.com>
Mon, 11 Dec 2017 11:47:55 +0000 (12:47 +0100)
search/engine/solr/classes/engine.php
search/engine/solr/classes/schema.php
search/engine/solr/version.php

index 1df982f..8ca37e2 100644 (file)
@@ -100,6 +100,13 @@ class engine extends \core_search\engine {
      */
     protected $skippeddocs = 0;
 
+    /**
+     * Solr server major version.
+     *
+     * @var int
+     */
+    protected $solrmajorversion = null;
+
     /**
      * Initialises the search engine configuration.
      *
@@ -889,6 +896,9 @@ class engine extends \core_search\engine {
 
         $url = $this->get_connection_url('/update/extract');
 
+        // Return results as XML.
+        $url->param('wt', 'xml');
+
         // This will prevent solr from automatically making fields for every tika output.
         $url->param('uprefix', 'ignored_');
 
@@ -1122,12 +1132,18 @@ class engine extends \core_search\engine {
      * @return int
      */
     public function get_solr_major_version() {
+        if ($this->solrmajorversion !== null) {
+            return $this->solrmajorversion;
+        }
+
         // We should really ping first the server to see if the specified indexname is valid but
         // we want to minimise solr server requests as they are expensive. system() emits a warning
         // if it can not connect to the configured index in the configured server.
         $systemdata = @$this->get_search_client()->system();
         $solrversion = $systemdata->getResponse()->offsetGet('lucene')->offsetGet('solr-spec-version');
-        return intval(substr($solrversion, 0, strpos($solrversion, '.')));
+        $this->solrmajorversion = intval(substr($solrversion, 0, strpos($solrversion, '.')));
+
+        return $this->solrmajorversion;
     }
 
     /**
index f9e79cc..86bd777 100644 (file)
@@ -86,8 +86,7 @@ class schema {
      */
     public function can_setup_server() {
 
-        $engine = new \search_solr\engine();
-        $status = $engine->is_server_configured();
+        $status = $this->engine->is_server_configured();
         if ($status !== true) {
             return $status;
         }
@@ -95,7 +94,7 @@ class schema {
         // At this stage we know that the server is properly configured with a valid host:port and indexname.
         // We're not too concerned about repeating the SolrClient::system() call (already called in
         // is_server_configured) because this is just a setup script.
-        if ($engine->get_solr_major_version() < 5) {
+        if ($this->engine->get_solr_major_version() < 5) {
             // Schema setup script only available for 5.0 onwards.
             return get_string('schemasetupfromsolr5', 'search_solr');
         }
@@ -182,11 +181,13 @@ class schema {
             if (!isset($data['type']) || !isset($data['stored']) || !isset($data['indexed'])) {
                 throw new \coding_exception($fieldname . ' does not define all required field params: type, stored and indexed.');
             }
+            $type = $this->doc_field_to_solr_field($data['type']);
+
             // Changing default multiValued value to false as we want to match values easily.
             $params = array(
                 'add-field' => array(
                     'name' => $fieldname,
-                    'type' => ($data['type'] === 'text' ? 'text_general' : $data['type']),
+                    'type' => $type,
                     'stored' => $data['stored'],
                     'multiValued' => false,
                     'indexed' => $data['indexed']
@@ -245,6 +246,7 @@ class schema {
                     // All these field attributes are set when fields are added through this script and should
                     // be returned and match the defined field's values.
 
+                    $expectedsolrfield = $this->doc_field_to_solr_field($data['type']);
                     if (empty($results->field) || !isset($results->field->type) ||
                             !isset($results->field->multiValued) || !isset($results->field->indexed) ||
                             !isset($results->field->stored)) {
@@ -252,14 +254,13 @@ class schema {
                         throw new \moodle_exception('errorcreatingschema', 'search_solr', '',
                             get_string('schemafieldautocreated', 'search_solr', $fieldname));
 
-                    } else if (($results->field->type !== $data['type'] &&
-                                ($data['type'] !== 'text' || $results->field->type !== 'text_general')) ||
-                                $results->field->multiValued !== false ||
-                                $results->field->indexed !== $data['indexed'] ||
-                                $results->field->stored !== $data['stored']) {
+                    } else if ($results->field->type !== $expectedsolrfield ||
+                            $results->field->multiValued !== false ||
+                            $results->field->indexed !== $data['indexed'] ||
+                            $results->field->stored !== $data['stored']) {
 
-                            throw new \moodle_exception('errorcreatingschema', 'search_solr', '',
-                                get_string('schemafieldautocreated', 'search_solr', $fieldname));
+                        throw new \moodle_exception('errorcreatingschema', 'search_solr', '',
+                            get_string('schemafieldautocreated', 'search_solr', $fieldname));
                     } else {
                         // The field already exists and it is properly defined, no need to create it.
                         unset($fields[$fieldname]);
@@ -309,4 +310,34 @@ class schema {
         }
 
     }
+
+    /**
+     * Returns the solr field type from the document field type string.
+     *
+     * @param string $datatype
+     * @return string
+     */
+    private function doc_field_to_solr_field($datatype) {
+        $type = $datatype;
+
+        $solrversion = $this->engine->get_solr_major_version();
+
+        switch($datatype) {
+            case 'text':
+                $type = 'text_general';
+                break;
+            case 'int':
+                if ($solrversion >= 7) {
+                    $type = 'pint';
+                }
+                break;
+            case 'tdate':
+                if ($solrversion >= 7) {
+                    $type = 'pdate';
+                }
+                break;
+        }
+
+        return $type;
+    }
 }
index 2bc7457..6f4658f 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2017111300;
+$plugin->version = 2017111700;
 $plugin->requires = 2017110800;
 $plugin->component = 'search_solr';