/**
  * This function returns an array of fields that can be passed to search engine.
  * @param Array $options
  * @param boolean $prefixed Add module name prefix (i.e. Contacts.first_name)
  * @return Array array of fields
  */
 protected function getSearchFields($options, $prefixed = true)
 {
     $fields = array();
     // determine list of modules/fields
     $allFieldDefs = array();
     if (!empty($options['moduleFilter'])) {
         foreach ($options['moduleFilter'] as $module) {
             $allFieldDefs[$module] = SugarSearchEngineMetadataHelper::retrieveFtsEnabledFieldsPerModule($module);
         }
     } else {
         $allFieldDefs = SugarSearchEngineMetadataHelper::retrieveFtsEnabledFieldsForAllModules();
     }
     // build list of fields with optional boost values (i.e. Accouns.name^3)
     foreach ($allFieldDefs as $module => $fieldDefs) {
         foreach ($fieldDefs as $fieldName => $fieldDef) {
             // skip non-supported field types
             $ftsType = $this->mapper->getFtsTypeFromDef($fieldDef);
             if (!$ftsType || in_array($ftsType['type'], $this->ignoreSearchTypes)) {
                 $this->logger->debug("Elastic: Ignoring unsupported type in query for {$module}/{$fieldName}");
                 continue;
             }
             // base field name
             if ($prefixed) {
                 $fieldName = $module . '.' . $fieldName;
             }
             // To enable a field for user search we require a boost value. There may be other fields
             // we index into Elastic but which should not be user searchable. We use the boost value
             // being set or not to distinguish between both scenarios. For example for extended facets
             // and related fields we can store additional fields or non analyzed data. While we need
             // those fields being indexed, we do not want the user to be able to hit those when
             // performing a search.
             if (empty($fieldDef['full_text_search']['boost'])) {
                 $this->logger->debug("Elastic: skipping {$module}/{$fieldName} for search field (no boost set)");
                 continue;
             } else {
                 if (!empty($options['addSearchBoosts'])) {
                     $fieldName .= '^' . $fieldDef['full_text_search']['boost'];
                 }
                 $fields[] = $fieldName;
             }
         }
     }
     return $fields;
 }
Ejemplo n.º 2
0
 /**
  *
  * Load facet definitions from enabled FTS module fieldDefs
  * @param string $module
  * @return array
  */
 protected function loadFacetDefs($module)
 {
     if (isset($this->facetDefs[$module])) {
         return $this->facetDefs[$module];
     }
     $this->facetDefs[$module] = array();
     $fieldDefs = SugarSearchEngineMetadataHelper::retrieveFtsEnabledFieldsPerModule($module);
     foreach ($fieldDefs as $fieldName => $fieldDef) {
         // skip non-facet defs
         if (empty($fieldDef['full_text_search']['facet'])) {
             continue;
         }
         $facet = $fieldDef['full_text_search']['facet'];
         // the type needs to be defined to be valid
         if (is_array($facet) && !empty($facet['type'])) {
             // set empty options array if nothing specified
             if (empty($facet['options']) || !is_array($facet['options'])) {
                 $facet['options'] = array();
             }
             // set defaults for ui_type and label
             $facet['ui_type'] = empty($facet['ui_type']) ? 'checkbox' : $facet['ui_type'];
             $facet['label'] = empty($facet['label']) ? 'LBL_FACET_NOT_SET' : $facet['label'];
             $this->facetDefs[$module][$fieldName] = $facet;
         }
     }
     return $this->facetDefs[$module];
 }
 /**
  * Main function that handles the indexing of a bean and is called by the job queue system.
  *
  * @param $data
  */
 public function run($module)
 {
     $serverOK = $this->updateFTSServerStatus();
     if ($serverOK != true) {
         $GLOBALS['log']->fatal('FTS Server is down, postponing the job for full index.');
         $this->schedulerJob->postponeJob(null, $this->postpone_job_time);
         return true;
     }
     $this->db->commit();
     $GLOBALS['log']->info("Going to index all records in module {$module} ");
     $startTime = microtime(true);
     $fieldDefinitions = SugarSearchEngineMetadataHelper::retrieveFtsEnabledFieldsPerModule($module);
     if (!empty($fieldDefinitions)) {
         $count = $this->indexRecords($module, $fieldDefinitions);
     } else {
         $GLOBALS['log']->fatal(sprintf('Fields of %s are not enabled for Full Text Search', $module));
         $this->schedulerJob->resolveJob(SchedulersJob::JOB_STATUS_DONE);
         return true;
     }
     if ($count == -1) {
         $GLOBALS['log']->fatal('FTS failed to index records, postponing job for next cron');
         $this->schedulerJob->postponeJob(null, $this->postpone_job_time);
         return true;
     }
     // stats logging
     $totalTime = number_format(round(microtime(true) - $startTime, 2), 2);
     $avgRecs = $count != 0 && $totalTime != 0 ? number_format(round($count / $totalTime, 2), 2) : 0;
     $GLOBALS['log']->info(sprintf("FTS Consumer %s processed %s record(s) in %s secs, records per sec: %s", $this->schedulerJob->name, $count, $totalTime, $avgRecs));
     // Mark the job that as pending so we can be invoked later again - this is considered to be a persistent job
     $this->schedulerJob->postponeJob(null, $this->postpone_job_time);
     return true;
 }