public function SearchApiSolrBackend::search in Search API Solr 8.2
Same name and namespace in other branches
- 8.3 src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::search()
- 8 src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::search()
- 4.x src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::search()
Options on $query prefixed by 'solr_param_' will be passed natively to Solr as query parameter without the prefix. For example you can set the "Minimum Should Match" parameter 'mm' to '75%' like this:
$query
->setOption('solr_param_mm', '75%');
Overrides BackendSpecificInterface::search
File
- src/
Plugin/ search_api/ backend/ SearchApiSolrBackend.php, line 1001
Class
- SearchApiSolrBackend
- Apache Solr backend for search api.
Namespace
Drupal\search_api_solr\Plugin\search_api\backendCode
public function search(QueryInterface $query) {
$this
->finalizeIndex($query
->getIndex());
if ($query
->getOption('solr_streaming_expression', FALSE)) {
$solarium_result = $this
->executeStreamingExpression($query);
// Extract results.
$search_api_result_set = $this
->extractResults($query, $solarium_result);
$this->moduleHandler
->alter('search_api_solr_search_results', $search_api_result_set, $query, $solarium_result);
$this
->postQuery($search_api_result_set, $query, $solarium_result);
}
else {
$mlt_options = $query
->getOption('search_api_mlt');
if (!empty($mlt_options)) {
$query
->addTag('mlt');
}
// Call an object oriented equivalent to hook_search_api_query_alter().
$this
->alterSearchApiQuery($query);
// Get field information.
/** @var \Drupal\search_api\Entity\Index $index */
$index = $query
->getIndex();
$index_id = $this
->getIndexId($index);
$field_names = $this
->getSolrFieldNames($index);
$connector = $this
->getSolrConnector();
$solarium_query = NULL;
$edismax = NULL;
$index_fields = $index
->getFields();
$index_fields += $this
->getSpecialFields($index);
if ($query
->hasTag('mlt')) {
$solarium_query = $this
->getMoreLikeThisQuery($query, $index_id, $index_fields, $field_names);
}
else {
// Instantiate a Solarium select query.
$solarium_query = $connector
->getSelectQuery();
$edismax = $solarium_query
->getEDisMax();
// Set searched fields.
$search_fields = $this
->getQueryFulltextFields($query);
$query_fields = [];
$query_fields_boosted = [];
foreach ($search_fields as $search_field) {
$query_fields[] = $field_names[$search_field];
/** @var \Drupal\search_api\Item\FieldInterface $field */
$field = $index_fields[$search_field];
$boost = $field
->getBoost() ? '^' . $field
->getBoost() : '';
$query_fields_boosted[] = $field_names[$search_field] . $boost;
}
$edismax
->setQueryFields(implode(' ', $query_fields_boosted));
try {
$highlight_config = $index
->getProcessor('highlight')
->getConfiguration();
if ($highlight_config['highlight'] != 'never') {
$this
->setHighlighting($solarium_query, $query, $query_fields);
}
} catch (SearchApiException $exception) {
// Highlighting processor is not enabled for this index. Just use the
// the index configuration.
$this
->setHighlighting($solarium_query, $query, $query_fields);
}
}
$options = $query
->getOptions();
// Set basic filters.
$filter_queries = $this
->getFilterQueries($query, $field_names, $index_fields, $options);
foreach ($filter_queries as $id => $filter_query) {
$solarium_query
->createFilterQuery('filters_' . $id)
->setQuery($filter_query['query'])
->addTags($filter_query['tags']);
}
// Set the Index (and site) filter.
$solarium_query
->createFilterQuery('index_filter')
->setQuery($this
->getIndexFilterQueryString($index));
// Set the list of fields to retrieve.
$this
->setFields($solarium_query, $field_names, $query
->getOption('search_api_retrieved_field_values', []));
// Set sorts.
$this
->setSorts($solarium_query, $query, $field_names);
// Set facet fields. setSpatial() might add more facets.
$this
->setFacets($query, $solarium_query, $field_names);
// Handle spatial filters.
if (isset($options['search_api_location'])) {
$this
->setSpatial($solarium_query, $options['search_api_location'], $field_names);
}
// Handle spatial filters.
if (isset($options['search_api_rpt'])) {
$this
->setRpt($solarium_query, $options['search_api_rpt'], $field_names);
}
// Handle field collapsing / grouping.
$grouping_options = $query
->getOption('search_api_grouping');
if (!empty($grouping_options['use_grouping'])) {
$this
->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);
foreach ($options as $option => $value) {
if (strpos($option, 'solr_param_') === 0) {
$solarium_query
->addParam(substr($option, 11), $value);
}
}
$this
->applySearchWorkarounds($solarium_query, $query);
try {
// Allow modules to alter the solarium query.
$this->moduleHandler
->alter('search_api_solr_query', $solarium_query, $query);
$this
->preQuery($solarium_query, $query);
// Since Solr 7.2 the edsimax query parser doesn't allow local
// parameters anymore. But since we don't want to force all modules that
// implemented our hooks to re-write their code, we transform the query
// back into a lucene query. flattenKeys() was adjusted accordingly, but
// in a backward compatible way.
// @see https://lucene.apache.org/solr/guide/7_2/solr-upgrade-notes.html#solr-7-2
if ($edismax) {
$parse_mode_id = $query
->getParseMode()
->getPluginId();
if ('terms' == $parse_mode_id) {
// Using the 'phrase' parse mode, Search API provides one big phrase
// as keys. Using the 'terms' parse mode, Search API provides chunks
// of single terms as keys. But these chunks might contain not just
// real terms but again a phrase if you enter something like this in
// the search box: term1 "term2 as phrase" term3. This will be
// converted in this keys array: ['term1', 'term2 as phrase',
// 'term3']. To have Solr behave like the database backend, these
// three "terms" should be handled like three phrases.
$parse_mode_id = 'phrase';
}
/** @var Query $solarium_query */
$params = $solarium_query
->getParams();
// Extract keys.
$keys = $query
->getKeys();
$query_fields_boosted = $edismax
->getQueryFields();
if (isset($params['defType']) && 'edismax' == $params['defType'] || !$query_fields_boosted) {
// Edismax was forced via API or the query fields were removed via
// API (like the multilingual backend does).
$keys = $this
->flattenKeys($keys, [], $parse_mode_id);
}
else {
$keys = $this
->flattenKeys($keys, explode(' ', $query_fields_boosted), $parse_mode_id);
}
if (!empty($keys)) {
// Set them.
$solarium_query
->setQuery($keys);
}
if (!isset($params['defType']) || 'edismax' != $params['defType']) {
$solarium_query
->removeComponent(ComponentAwareQueryInterface::COMPONENT_EDISMAX);
}
}
// Allow modules to alter the converted solarium query.
$this->moduleHandler
->alter('search_api_solr_converted_query', $solarium_query, $query);
// Send search request.
$response = $connector
->search($solarium_query);
$body = $response
->getBody();
if (200 != $response
->getStatusCode()) {
throw new SearchApiSolrException(strip_tags($body), $response
->getStatusCode());
}
$this
->alterSolrResponseBody($body, $query);
$response = new Response($body, $response
->getHeaders());
$solarium_result = $connector
->createSearchResult($solarium_query, $response);
// Extract results.
$search_api_result_set = $this
->extractResults($query, $solarium_result);
// Add warnings, if present.
if (!empty($warnings)) {
foreach ($warnings as $warning) {
$search_api_result_set
->addWarning($warning);
}
}
// Extract facets.
if ($solarium_result instanceof Result) {
if ($solarium_facet_set = $solarium_result
->getFacetSet()) {
$search_api_result_set
->setExtraData('facet_set', $solarium_facet_set);
if ($search_api_facets = $this
->extractFacets($query, $solarium_result, $field_names)) {
$search_api_result_set
->setExtraData('search_api_facets', $search_api_facets);
}
}
}
$this->moduleHandler
->alter('search_api_solr_search_results', $search_api_result_set, $query, $solarium_result);
$this
->postQuery($search_api_result_set, $query, $solarium_result);
} catch (\Exception $e) {
throw new SearchApiSolrException('An error occurred while trying to search with Solr: ' . $e
->getMessage(), $e
->getCode(), $e);
}
}
}