浏览代码

refactoring of materio_sapi search queries: 1 query hyper-restrictive followed by one more opened

bach 3 年之前
父节点
当前提交
60c4cf5451
共有 1 个文件被更改,包括 147 次插入90 次删除
  1. 147 90
      web/modules/custom/materio_sapi/src/Controller/Base.php

+ 147 - 90
web/modules/custom/materio_sapi/src/Controller/Base.php

@@ -27,94 +27,155 @@ class Base extends ControllerBase {
     // https://www.hashbangcode.com/article/drupal-8-date-search-boosting-search-api-and-solr-search
     // https://kgaut.net/blog/2018/drupal-8-search-api-effectuer-une-requete-dans-le-code.html
 
-    $this->index = Index::load('database');
+    $lang = \Drupal::languageManager()->getCurrentLanguage()->getId();
 
-    // // get solarium fileds name
-    // $solrFields = $this->index->getServerInstance()
-    //   ->getBackend()
-    //   ->getSolrFieldNames($this->index);
-    //
-    // // tag_tid"itm_tag_tid"
-    // // thesaurus_tid"itm_thesaurus_tid"
-    // $taxoSolrFieldsName = [];
-    // foreach (['tag_tid', 'thesaurus_tid'] as $f) {
-    //   $taxoSolrFieldsName[] = $solrFields[$f];
-    // }
+    $this->index = Index::load('database');
 
-    $this->query = $this->index->query();
+    $this->results = [
+      'uuids' => [],
+      'nids' => []
+    ];
 
-    // Change the parse mode for the search.
-    // Les différentes possibilités sont
-    //  - « direct » => Requête directe
-    //  - « terms » => Multiple words
-    //  - « phrase » => Single phrase
-    //  - " edismax " => ???
+    // AND QUERY
+    $this->and_query = $this->index->query(['offset'=>0,'limit'=>10000]);
+    // set parse mode and conjunction
     $parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')
-      ->createInstance('direct');
-    $parse_mode->setConjunction('OR');
-    $this->query->setParseMode($parse_mode);
-
+    ->createInstance('terms');
+    $parse_mode->setConjunction('AND');
+    $this->and_query->setParseMode($parse_mode);
     // Set fulltext search keywords and fields.
-    $this->query->keys($this->keys);
-    // $this->query->setFulltextFields(['field_reference']);
-
-    // Set additional conditions.
+    $this->and_query->keys($this->keys);
+    // $this->and_query->setFulltextFields(['field_reference']);
     // in case we search for material references like W0117
     if (preg_match_all('/[WTRPCMFGSO]\d{4}/i', $this->keys, $matches)) {
-      $ref_conditions = $this->query->createConditionGroup('OR');
+      $ref_conditions = $this->and_query->createConditionGroup('OR');
       foreach ($matches[0] as $key => $value) {
         $ref_conditions->addCondition('field_reference', $value);
       }
-      $this->query->addConditionGroup($ref_conditions);
+      $this->and_query->addConditionGroup($ref_conditions);
     }
     // in case of term id provided restrict the keys to taxo fields
     if ($this->term) {
-      // $term_conditions = $this->query->createConditionGroup('OR');
-      // $term = (int) $this->term;
-      // foreach (['tag_tid', 'thesaurus_tid'] as $field) {
-      //   $term_conditions->addCondition($field, $term);
-      // }
-      // $this->query->addConditionGroup($term_conditions);
+      $term_conditions = $this->and_query->createConditionGroup('OR');
+      $term = (int) $this->term;
+      foreach (['tag_tid', 'thesaurus_tid'] as $field) {
+        $term_conditions->addCondition($field, $term);
+      }
+      $this->and_query->addConditionGroup($term_conditions);
 
-      // INSTEAD TRY TO BOOST TTHE TAG AND THESAURUS FIELDS
+      // INSTEAD TRY TO BOOST THE TAG AND THESAURUS FIELDS
       // foreach ($taxoSolrFieldsName as $fname) {
       //   // $solarium_query->addParam('bf', "recip(abs(ms(NOW,{$solrField})),3.16e-11,10,0.1)");
       //   $bfparam = "if(gt(termfreq({$fname},{$this->term}),0),^21,0)";
-      //   $this->query->addParam('bf', $bfparam);
+      //   $this->or_query->addParam('bf', $bfparam);
       // }
-
-      $this->query->setOption('termid', $this->term);
+      // look @ materio_sapi_search_api_solr_query_alter in materio_sapi.module
+      // $this->or_query->setOption('termid', $this->term);
     }
-
-    // filter the search
+    // FILTERS
     if ($this->filters) {
-      $filters_conditions = $this->query->createConditionGroup('OR');
+      $filters_conditions = $this->and_query->createConditionGroup('AND');
       foreach ($this->filters as $filter) {
         $filter = (int) $filter;
         foreach (['tag_tid', 'thesaurus_tid'] as $field) {
           $filters_conditions->addCondition($field, $filter);
         }
       }
-      $this->query->addConditionGroup($filters_conditions);
+      $this->and_query->addConditionGroup($filters_conditions);
+    }else{
+      // Recherche uniquement sur le champ « body »
+      $this->and_query->setFulltextFields([
+        'thesaurus_name_0',
+        'thesaurus_synonyms_0',
+        'thesaurus_name_1',
+        'thesaurus_synonyms_1',
+        'thesaurus_name_2',
+        'thesaurus_synonyms_2',
+        'thesaurus_name_3',
+        'thesaurus_synonyms_3',
+        'thesaurus_name_4',
+        'thesaurus_synonyms_4',
+        'thesaurus_name',
+        'thesaurus_synonyms',
+        'tag_name',
+        'tag_synonyms'
+      ]);
     }
 
+
+
     // Restrict the search to specific languages.
-    $lang = \Drupal::languageManager()->getCurrentLanguage()->getId();
-    $this->query->setLanguages([$lang]);
+    $this->and_query->setLanguages([$lang]);
 
     // Do paging.
-    $this->query->range($this->offset, $this->limit);
+    // $this->and_query->range($this->offset, $this->limit);
+    // retrieve all results
+    // $this->and_query->range(0, -1);
 
     // Add sorting.
-    $this->query->sort('search_api_relevance', 'DESC');
+    $this->and_query->sort('search_api_relevance', 'DESC');
 
     // Set one or more tags for the query.
     // @see hook_search_api_query_TAG_alter()
     // @see hook_search_api_results_TAG_alter()
-    $this->query->addTag('materio_sapi_search');
+    $this->and_query->addTag('materio_sapi_search_and_query');
 
-    $this->results = $this->query->execute();
+    $and_results = $this->and_query->execute();
+
+    foreach ($and_results as $result) {
+      $this->results['uuids'][] = $result->getField('uuid')->getValues()[0];
+      $this->results['nids'][] = $result->getField('nid')->getValues()[0];
+    }
 
+    // 
+    // OR QUERY
+    // 
+    $this->or_query = $this->index->query(['offset'=>0,'limit'=>10000]);
+
+    // Change the parse mode for the search.
+    // Les différentes possibilités sont
+    //  - « direct » => Requête directe
+    //  - « terms » => Multiple words
+    //  - « phrase » => Single phrase
+    //  - " edismax " => ???
+    $or_parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')
+      ->createInstance('direct');
+    $or_parse_mode->setConjunction('OR');
+    $this->or_query->setParseMode($or_parse_mode);
+
+    // Set fulltext search keywords and fields.
+    $this->or_query->keys($this->keys);
+    // $this->or_query->setFulltextFields(['field_reference']);
+
+    // exclude results from and_query
+    $exclude_and_results_conditions = $this->or_query->createConditionGroup('AND');
+    foreach ($this->results['nids'] as $nid) {
+      $exclude_and_results_conditions->addCondition('nid', $nid, '<>');
+    }
+    $this->or_query->addConditionGroup($exclude_and_results_conditions);
+
+    // Restrict the search to specific languages.
+    $this->or_query->setLanguages([$lang]);
+
+    // Do paging.
+    // $this->or_query->range($this->offset, $this->limit);
+    // retrieve all results
+    // $this->or_query->range(0, -1);
+
+    // Add sorting.
+    $this->or_query->sort('search_api_relevance', 'DESC');
+
+    // Set one or more tags for the query.
+    // @see hook_search_api_query_TAG_alter()
+    // @see hook_search_api_results_TAG_alter()
+    $this->or_query->addTag('materio_sapi_search_or_query');
+
+    $or_results = $this->or_query->execute();
+
+    foreach ($or_results as $result) {
+      $this->results['uuids'][] = $result->getField('uuid')->getValues()[0];
+      $this->results['nids'][] = $result->getField('nid')->getValues()[0];
+    }
   }
 
   private function defaultQuery(){
@@ -138,6 +199,7 @@ class Base extends ControllerBase {
       ->count();
     $this->count = $this->count_query->execute();
   }
+
   /**
    * get params from request
    */
@@ -179,33 +241,24 @@ class Base extends ControllerBase {
 
       $resp['keys'] = $this->keys;
       $resp['term'] = $this->term;
-      $resp['count'] = $this->results->getResultCount();
+      // $resp['count'] = $this->results->getResultCount();
+      $resp['count'] = count($this->results['nids']);
       $resp['infos'] = t('The search found @count result(s) with keywords @keys.', array(
         "@count" => $resp['count'],
         "@keys" => $this->keys
       ));
 
 
-      $resp['options'] = $this->query->getOptions();
+      // $resp['options'] = $this->query->getOptions();
 
-      // $items = [];
-      $uuids = [];
-      $nids = [];
-      foreach ($this->results as $result) {
-        // $nid = $result->getField('nid')->getValues()[0];
-        // $uuid = $result->getField('uuid')->getValues()[0];
-        // $title = $result->getField('title')->getValues()[0]->getText();
-        // $items[] = [
-        //   'nid' => $nid,
-        //   'uuid' => $uuid,
-        //   'title' => $title,
-        // ];
-        $uuids[] = $result->getField('uuid')->getValues()[0];
-        $nids[] = $result->getField('nid')->getValues()[0];
-      }
-      // $resp['items'] = $items;
-      $resp['uuids'] = $uuids;
-      $resp['nids'] = $nids;
+      // $uuids = [];
+      // $nids = [];
+      // foreach ($this->results as $result) {
+      //   $uuids[] = $result->getField('uuid')->getValues()[0];
+      //   $nids[] = $result->getField('nid')->getValues()[0];
+      // }
+      $resp['nids'] = array_slice($this->results['nids'], $this->offset, $this->limit);
+      $resp['uuids'] = array_slice($this->results['uuids'], $this->offset, $this->limit);
     } else {
       // no keys or terms to search for
       // display the default base page
@@ -254,30 +307,34 @@ class Base extends ControllerBase {
     if ($this->keys) {
       $resp['#title'] = $this->keys;
 
-      $this->sapiQuery();
-
-      $node_view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
+      // $this->sapiQuery();
 
-      $items = $this->results->getResultItems();
-      $this->items = [];
-      foreach ($items as $item) {
-        // \Drupal::logger('materio_sapi')->notice(print_r($item, true));
-        try {
-          /** @var \Drupal\Core\Entity\EntityInterface $entity */
-          $entity = $item->getOriginalObject()->getValue();
-        }
-        catch (SearchApiException $e) {
-          continue;
-        }
-        if (!$entity) {
-          continue;
-        }
-        // TODO: define dynamicly viewmode
-        $this->items[] = $node_view_builder->view($entity, 'teaser');
+      // $node_storage = \Drupal::entityTypeManager()->getStorage('node');
+      // $node_view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
+
+      // // $items = $this->results->getResultItems();
+      // $nids = $this->results['nids'];
+      // $this->items = [];
+      // foreach ($nids as $nid) {
+      //   // \Drupal::logger('materio_sapi')->notice(print_r($nid, true));
+      //   try {
+      //     /** @var \Drupal\Core\Entity\EntityInterface $entity */
+      //     // $entity = $item->getOriginalObject()->getValue();
+      //     $entity = $node_storage->load($nid);
+      //   }
+      //   catch (SearchApiException $e) {
+      //     continue;
+      //   }
+      //   if (!$entity) {
+      //     continue;
+      //   }
+      //   // TODO: define dynamicly viewmode
+      //   $this->items[] = $node_view_builder->view($entity, 'teaser');
 
-      }
+      // }
 
-      $resp['items'] = $this->items;
+      // $resp['items'] = $this->items;
+      $resp['items'] = [];
     }else{
       $resp['#markup'] = t("no keys to search for");
     }