/**
  * Rebuild the index. If a Store ID or Product IDs are specified it is only rebuilt for those.
  *
  * @param int|null $storeId - Store View Id, null or 0 means all storeViews
  * @param int[]|null $productIds - Product Entity Id(s)
  * @param bool $cleanFirst - If set to true the index will be cleared first
  * @return bool                  - True on success
  */
 public function rebuildIndex($storeId = null, $productIds = null, $cleanFirst = false)
 {
     if (!$this->_working) {
         return false;
     }
     $result = false;
     try {
         $coreResource = Mage::getSingleton('core/resource');
         $readAdapter = $coreResource->getConnection('core_read');
         $select = $readAdapter->select();
         $select->from($coreResource->getTableName('catalogsearch/fulltext'), array('product_id', 'store_id', 'data_index', 'fulltext_id'));
         if (empty($storeId)) {
             $select->where('store_id IN (?)', $this->getEnabledStoreIds());
         } else {
             $select->where('store_id = ?', $storeId);
         }
         if (!empty($productIds)) {
             if (is_numeric($productIds)) {
                 $select->where('product_id = ?', $productIds);
             } else {
                 if (is_array($productIds)) {
                     $select->where('product_id IN (?)', $productIds);
                 }
             }
         }
         $products = $readAdapter->query($select);
         if (!$products->rowCount()) {
             // No matching products, nothing to update, consider OK.
             $result = true;
         } else {
             if ($cleanFirst) {
                 $deleteQuery = $this->_client->createUpdate();
                 $deleteQuery->addDeleteQuery($this->_getDeleteQueryText($storeId, $productIds));
                 // No commit yet, will be done after BufferedAdd
                 $this->_client->update($deleteQuery);
             }
             /** @var Solarium\Plugin\BufferedAdd\BufferedAdd $buffer */
             $buffer = $this->_client->getPlugin('bufferedadd');
             $buffer->setBufferSize(max(1, $this->getConf('reindexing/buffersize', $storeId)));
             $buffer->setEndpoint('update');
             /** @noinspection PhpAssignmentInConditionInspection */
             while ($product = $products->fetch()) {
                 $text = $product['data_index'];
                 $text = preg_replace('/\\s*\\,\\s*+/', ' ', $text);
                 // Replace comma separation by spaces
                 $text = $this->_filterString($text);
                 $data = array('id' => intval($product['fulltext_id']), 'product_id' => intval($product['product_id']), 'store_id' => intval($product['store_id']), 'text' => $text);
                 $buffer->createDocument($data);
             }
             $solariumResult = $buffer->commit();
             $this->optimize();
             // ignore result
             $result = $this->processResult($solariumResult, 'flushing buffered add');
         }
     } catch (Exception $e) {
         $this->_lastError = $e;
         Mage::log(sprintf('%s->%s: %s', __CLASS__, __FUNCTION__, $e->getMessage()), Zend_Log::ERR);
     }
     return $result;
 }
Beispiel #2
0
 /**
  * Changes the query to a "More Like This"  query.
  */
 public function setMoreLikeThis(Query &$solarium_query, QueryInterface $query, $mlt_options = array(), $index_fields = array(), $fields)
 {
     $solarium_query = $this->solr->createMoreLikeThis(array('handler' => 'select'));
     // The fields to look for similarities in.
     if (empty($mlt_options['fields'])) {
         return;
     }
     $mlt_fl = array();
     foreach ($mlt_options['fields'] as $mlt_field) {
         // Solr 4 has a bug which results in numeric fields not being supported
         // in MLT queries.
         // Date fields don't seem to be supported at all.
         $version = $this->getSolrVersion();
         if ($fields[$mlt_field][0] === 'd' || $version == 4 && in_array($fields[$mlt_field][0], array('i', 'f'))) {
             continue;
         }
         $mlt_fl[] = $fields[$mlt_field];
         // For non-text fields, set minimum word length to 0.
         if (isset($index_fields[$mlt_field]) && !SearchApiUtility::isTextType($index_fields[$mlt_field]->getType())) {
             $solarium_query->addParam('f.' . $fields[$mlt_field] . '.mlt.minwl', 0);
         }
     }
     //$solarium_query->setHandler('mlt');
     $solarium_query->setMltFields($mlt_fl);
     /** @var \Solarium\Plugin\CustomizeRequest\CustomizeRequest $customizer */
     $customizer = $this->solr->getPlugin('customizerequest');
     $customizer->createCustomization('id')->setType('param')->setName('qt')->setValue('mlt');
     // @todo Make sure these configurations are correct
     $solarium_query->setMinimumDocumentFrequency(1);
     $solarium_query->setMinimumTermFrequency(1);
 }
 /**
  * Get document urls and id from solr.
  * @param array $metadata
  * @return null|\Solarium\Core\Plugin\PluginInterface
  */
 public function getDocumentUrlsInCore($metadata)
 {
     $this->setCoreNameFromMetadata($metadata);
     $query = $this->client->createSelect();
     $query->setQuery('*:*');
     $query->setFields(['url', 'id']);
     $prefetch = $this->client->getPlugin('prefetchiterator');
     $prefetch->setPrefetch(100);
     //fetch 2 rows per query (for real world use this can be way higher)
     $prefetch->setQuery($query);
     return $prefetch;
 }
Beispiel #4
0
 /**
  * @param array $entities
  */
 public function synchronizeIndex($entities)
 {
     /** @var BufferedAdd $buffer */
     $buffer = $this->solrClientCore->getPlugin('bufferedadd');
     $buffer->setBufferSize(500);
     foreach ($entities as $entity) {
         $metaInformations = $this->metaInformationFactory->loadInformation($entity);
         if (!$this->addToIndex($metaInformations, $entity)) {
             continue;
         }
         $doc = $this->toDocument($metaInformations);
         $buffer->addDocument($doc);
     }
     $buffer->commit();
 }
 /**
  * {@inheritdoc}
  */
 public function search(QueryInterface $query)
 {
     // Reset request handler.
     $this->request_handler = NULL;
     // Get field information.
     /** @var \Drupal\search_api\Entity\Index $index */
     $index = $query->getIndex();
     $index_id = $this->getIndexId($index->id());
     $field_names = $this->getFieldNames($index);
     $field_names_single_value = $this->getFieldNames($index, TRUE);
     // Get Solr connection.
     $this->connect();
     // Instantiate a Solarium select query.
     $solarium_query = $this->solr->createSelect();
     // Extract keys.
     $keys = $query->getKeys();
     if (is_array($keys)) {
         $keys = $this->getSolrHelper()->flattenKeys($keys);
     }
     // Set them
     $solarium_query->setQuery($keys);
     unset($keys);
     $returned_fields = array('item_id', 'score');
     if (!$this->configuration['site_hash']) {
         $returned_fields[] = 'hash';
     }
     $solarium_query->setFields($returned_fields);
     // Set searched fields.
     $options = $query->getOptions();
     $search_fields = $this->getQueryFulltextFields($query);
     // Get the index fields to be able to retrieve boosts.
     $index_fields = $index->getFields();
     $query_fields = array();
     foreach ($search_fields as $search_field) {
         /** @var \Solarium\QueryType\Update\Query\Document\Document $document */
         $document = $index_fields[$search_field];
         $boost = $document->getBoost() ? '^' . $document->getBoost() : '';
         $query_fields[] = $field_names[$search_field] . $boost;
     }
     $solarium_query->getEDisMax()->setQueryFields(implode(' ', $query_fields));
     // Handle More Like This requests
     $mlt_options = $query->getOption('search_api_mlt');
     if ($mlt_options) {
         $index_fields = $index->getFields();
         $this->getSolrHelper()->setMoreLikeThis($solarium_query, $query, $mlt_options, $index_fields, $field_names);
         // Override the search key by setting it to the solr document id
         // we want to compare it with
         // @todo. Figure out how we can set MLT earlier in the process
         // so we do not do unnecessary function calls
         $id = $this->createId($index_id, $mlt_options['id']);
         $id = static::getQueryHelper()->escapePhrase($id);
         $solarium_query->setQuery('id:' . $id);
     }
     // Set basic filters.
     $conditions_queries = $this->createFilterQueries($query->getConditionGroup(), $field_names, $index->getFields());
     foreach ($conditions_queries as $id => $conditions_query) {
         $solarium_query->createFilterQuery('filters_' . $id)->setQuery($conditions_query);
     }
     // Set the Index filter
     $solarium_query->createFilterQuery('index_id')->setQuery('index_id:' . static::getQueryHelper($solarium_query)->escapePhrase($index_id));
     // Set the site hash filter, if enabled.
     if ($this->configuration['site_hash']) {
         $site_hash = $this->getQueryHelper()->escapePhrase(SearchApiSolrUtility::getSiteHash());
         $solarium_query->createFilterQuery('site_hash')->setQuery('hash:' . $site_hash);
     }
     // Set sorts.
     $this->solrHelper->setSorts($solarium_query, $query, $field_names_single_value);
     // Set facet fields.
     $facets = $query->getOption('search_api_facets', array());
     $this->setFacets($facets, $field_names, $solarium_query);
     // Set highlighting.
     $excerpt = !empty($this->configuration['excerpt']) ? true : false;
     $highlight_data = !empty($this->configuration['highlight_data']) ? true : false;
     $this->getSolrHelper()->setHighlighting($solarium_query, $query, $excerpt, $highlight_data);
     // Handle spatial filters.
     $spatial_options = $query->getOption('search_api_location');
     if ($spatial_options) {
         $this->solrHelper->setSpatial($solarium_query, $query, $spatial_options, $field_names);
     }
     // Handle field collapsing / grouping.
     $grouping_options = $query->getOption('search_api_grouping');
     if (!empty($grouping_options['use_grouping'])) {
         $this->solrHelper->setGrouping($solarium_query, $query, $grouping_options, $index_fields, $field_names);
     }
     if (isset($options['offset'])) {
         $solarium_query->setStart($options['offset']);
     }
     $rows = isset($options['limit']) ? $options['limit'] : 1000000;
     $solarium_query->setRows($rows);
     if (!empty($options['search_api_spellcheck'])) {
         $solarium_query->getSpellcheck();
     }
     /**
      * @todo Make this more configurable so that views can choose which fields
      * it wants to fetch
      */
     if (!empty($this->configuration['retrieve_data'])) {
         $solarium_query->setFields(array('*', 'score'));
     }
     // Allow modules to alter the query
     try {
         $this->moduleHandler->alter('search_api_solr_query', $solarium_query, $query);
         $this->preQuery($solarium_query, $query);
         // Use the 'postbigrequest' plugin if no specific http method is
         // configured. The plugin needs to be loaded before the request is
         // created.
         if ($this->configuration['http_method'] == 'AUTO') {
             $this->solr->getPlugin('postbigrequest');
         }
         // Use the manual method of creating a Solarium request so we can control
         // the HTTP method.
         $request = $this->solr->createRequest($solarium_query);
         // Set the configured HTTP method.
         if ($this->configuration['http_method'] == 'POST') {
             $request->setMethod(Request::METHOD_POST);
         } elseif ($this->configuration['http_method'] == 'GET') {
             $request->setMethod(Request::METHOD_GET);
         }
         // Set HTTP Basic Authentication parameter, if login data was set.
         if (strlen($this->configuration['http_user']) && strlen($this->configuration['http_pass'])) {
             $request->setAuthentication($this->configuration['http_user'], $this->configuration['http_pass']);
         }
         // Send search request.
         $response = $this->solr->executeRequest($request);
         $resultset = $this->solr->createResult($solarium_query, $response);
         // Extract results.
         $results = $this->extractResults($query, $resultset);
         // Add warnings, if present.
         if (!empty($warnings)) {
             foreach ($warnings as $warning) {
                 $results->addWarning($warning);
             }
         }
         // Extract facets.
         if ($resultset instanceof Result) {
             if ($facets = $this->extractFacets($query, $resultset)) {
                 $results->setExtraData('search_api_facets', $facets);
             }
         }
         $this->moduleHandler->alter('search_api_solr_search_results', $results, $query, $resultset);
         $this->postQuery($results, $query, $resultset);
         return $results;
     } catch (SearchApiException $e) {
         throw new SearchApiException(t('An error occurred while trying to search with Solr: @msg.', array('@msg' => $e->getMessage())));
     }
 }