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

This commit is contained in:
Bachir Soussi Chiadmi 2021-10-26 21:33:24 +02:00
parent c246934fb3
commit 60c4cf5451
1 changed files with 158 additions and 101 deletions

View File

@ -27,21 +27,110 @@ 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
$lang = \Drupal::languageManager()->getCurrentLanguage()->getId();
$this->index = Index::load('database');
// // 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->results = [
'uuids' => [],
'nids' => []
];
$this->query = $this->index->query();
// 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('terms');
$parse_mode->setConjunction('AND');
$this->and_query->setParseMode($parse_mode);
// Set fulltext search keywords and fields.
$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->and_query->createConditionGroup('OR');
foreach ($matches[0] as $key => $value) {
$ref_conditions->addCondition('field_reference', $value);
}
$this->and_query->addConditionGroup($ref_conditions);
}
// in case of term id provided restrict the keys to taxo fields
if ($this->term) {
$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 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->or_query->addParam('bf', $bfparam);
// }
// look @ materio_sapi_search_api_solr_query_alter in materio_sapi.module
// $this->or_query->setOption('termid', $this->term);
}
// FILTERS
if ($this->filters) {
$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->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.
$this->and_query->setLanguages([$lang]);
// Do paging.
// $this->and_query->range($this->offset, $this->limit);
// retrieve all results
// $this->and_query->range(0, -1);
// Add sorting.
$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->and_query->addTag('materio_sapi_search_and_query');
$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
@ -49,72 +138,44 @@ class Base extends ControllerBase {
// - « terms » => Multiple words
// - « phrase » => Single phrase
// - " edismax " => ???
$parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')
$or_parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')
->createInstance('direct');
$parse_mode->setConjunction('OR');
$this->query->setParseMode($parse_mode);
$or_parse_mode->setConjunction('OR');
$this->or_query->setParseMode($or_parse_mode);
// Set fulltext search keywords and fields.
$this->query->keys($this->keys);
// $this->query->setFulltextFields(['field_reference']);
$this->or_query->keys($this->keys);
// $this->or_query->setFulltextFields(['field_reference']);
// Set additional conditions.
// 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');
foreach ($matches[0] as $key => $value) {
$ref_conditions->addCondition('field_reference', $value);
}
$this->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);
// INSTEAD TRY TO BOOST TTHE 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->query->setOption('termid', $this->term);
}
// filter the search
if ($this->filters) {
$filters_conditions = $this->query->createConditionGroup('OR');
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);
// 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.
$lang = \Drupal::languageManager()->getCurrentLanguage()->getId();
$this->query->setLanguages([$lang]);
$this->or_query->setLanguages([$lang]);
// Do paging.
$this->query->range($this->offset, $this->limit);
// $this->or_query->range($this->offset, $this->limit);
// retrieve all results
// $this->or_query->range(0, -1);
// Add sorting.
$this->query->sort('search_api_relevance', 'DESC');
$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->query->addTag('materio_sapi_search');
$this->or_query->addTag('materio_sapi_search_or_query');
$this->results = $this->query->execute();
$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();
// $this->sapiQuery();
$node_view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
// $node_storage = \Drupal::entityTypeManager()->getStorage('node');
// $node_view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
$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');
// // $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");
}