protected function SearchApiSolrBackend::setSpatial in Search API Solr 8
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::setSpatial()
- 8.2 src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::setSpatial()
- 4.x src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::setSpatial()
Adds spatial features to the search query.
Parameters
\Solarium\QueryType\Select\Query\Query $solarium_query: The solr query.
array $spatial_options: The spatial options to add.
array $field_names: The field names, to add the spatial options for.
Throws
\Drupal\search_api_solr\SearchApiSolrException
1 call to SearchApiSolrBackend::setSpatial()
- SearchApiSolrBackend::search in src/
Plugin/ search_api/ backend/ SearchApiSolrBackend.php - 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:
File
- src/
Plugin/ search_api/ backend/ SearchApiSolrBackend.php, line 2578
Class
- SearchApiSolrBackend
- Apache Solr backend for search api.
Namespace
Drupal\search_api_solr\Plugin\search_api\backendCode
protected function setSpatial(Query $solarium_query, array $spatial_options, $field_names = []) {
if (count($spatial_options) > 1) {
throw new SearchApiSolrException('Only one spatial search can be handled per query.');
}
$spatial = reset($spatial_options);
$solr_field = $field_names[$spatial['field']];
$distance_field = $spatial['field'] . '__distance';
$solr_distance_field = $field_names[$distance_field];
$spatial['lat'] = (double) $spatial['lat'];
$spatial['lon'] = (double) $spatial['lon'];
$spatial['radius'] = isset($spatial['radius']) ? (double) $spatial['radius'] : 0.0;
$spatial['min_radius'] = isset($spatial['min_radius']) ? (double) $spatial['min_radius'] : 0.0;
if (!isset($spatial['filter_query_conditions'])) {
$spatial['filter_query_conditions'] = [];
}
$spatial['filter_query_conditions'] += [
'field' => $solr_field,
'value' => $spatial['radius'],
'operator' => '<',
];
// Add a field to the result set containing the calculated distance.
$solarium_query
->addField($solr_distance_field . ':geodist()');
// Set the common spatial parameters on the query.
$spatial_query = $solarium_query
->getSpatial();
$spatial_query
->setDistance($spatial['radius']);
$spatial_query
->setField($solr_field);
$spatial_query
->setPoint($spatial['lat'] . ',' . $spatial['lon']);
// Add the conditions of the spatial query. This might adust the values of
// 'radius' and 'min_radius' required later for facets.
$solarium_query
->createFilterQuery($solr_field)
->setQuery($this
->createLocationFilterQuery($spatial));
// Tell solr to sort by distance if the field is given by Search API.
$sorts = $solarium_query
->getSorts();
if (isset($sorts[$solr_distance_field])) {
$new_sorts = [];
foreach ($sorts as $key => $order) {
if ($key == $solr_distance_field) {
$new_sorts['geodist()'] = $order;
}
else {
$new_sorts[$key] = $order;
}
}
$solarium_query
->clearSorts();
$solarium_query
->setSorts($new_sorts);
}
// Change the facet parameters for spatial fields to return distance
// facets.
$facet_set = $solarium_query
->getFacetSet();
if (!empty($facet_set)) {
/** @var \Solarium\QueryType\Select\Query\Component\Facet\Field[] $facets */
$facets = $facet_set
->getFacets();
foreach ($facets as $delta => $facet) {
$facet_options = $facet
->getOptions();
if ($facet_options['field'] != $solr_distance_field) {
continue;
}
$facet_set
->removeFacet($delta);
$limit = $facet
->getLimit();
// @todo Check if these defaults make any sense.
$steps = $limit > 0 ? $limit : 5;
$step = ($spatial['radius'] - $spatial['min_radius']) / $steps;
for ($i = 0; $i < $steps; $i++) {
$distance_min = $spatial['min_radius'] + $step * $i;
// @todo $step - 1 means 1km less. That opens a gap in the facets of
// 1km that is not covered.
$distance_max = $distance_min + $step - 1;
// Define our own facet key to transport the min and max values.
// These will be extracted in extractFacets().
$key = "spatial-{$distance_field}-{$distance_min}-{$distance_max}";
// Due to a limitation/bug in Solarium, it is not possible to use
// setQuery method for geo facets.
// So the key is misused to get a correct query.
// @see https://github.com/solariumphp/solarium/issues/229
$facet_set
->createFacetQuery($key . ' frange l=' . $distance_min . ' u=' . $distance_max)
->setQuery('geodist()');
}
}
}
}