protected function SearchApiDbService::getFacets in Search API Database Search 7
Computes facets for a search query.
Parameters
SearchApiQueryInterface $query: The search query for which facets should be computed.
SelectQueryInterface $db_query: A database select query which returns all results of that search query.
Return value
array An array of facets, as specified by the search_api_facets feature.
1 call to SearchApiDbService::getFacets()
- SearchApiDbService::search in ./
service.inc - Executes a search on the server represented by this object.
File
- ./
service.inc, line 1924 - Contains SearchApiDbService.
Class
- SearchApiDbService
- Indexes and searches items using the database.
Code
protected function getFacets(SearchApiQueryInterface $query, SelectQueryInterface $db_query) {
try {
// Add a tag to the database query to identify it as a facet base query.
$db_query
->addTag('search_api_db_facets_base');
// Store the results of the query in a temporary table to run facet
// queries on it afterwards.
$table = $this
->getTemporaryResultsTable($db_query);
if (!$table) {
return array();
}
$fields = $this
->getFieldInfo($query
->getIndex());
$ret = array();
foreach ($query
->getOption('search_api_facets') as $key => $facet) {
if (empty($fields[$facet['field']])) {
$this->warnings[] = t('Unknown facet field @field.', array(
'@field' => $facet['field'],
));
continue;
}
$field = $fields[$facet['field']];
if (empty($facet['operator']) || $facet['operator'] != 'or') {
// All the AND facets can use the main query.
$select = $this->connection
->select($table, 't');
}
else {
// For OR facets, we need to build a different base query that
// excludes the facet filters applied to the facet.
$or_query = clone $query;
$filters =& $or_query
->getFilter()
->getFilters();
$tag = 'facet:' . $facet['field'];
foreach ($filters as $filter_id => $filter) {
if ($filter instanceof SearchApiQueryFilterInterface && $filter
->hasTag($tag)) {
unset($filters[$filter_id]);
}
}
$or_db_query = $this
->createDbQuery($or_query, $fields);
$select = $this->connection
->select($or_db_query, 't');
}
// Add tags and metadata.
$select
->addTag('search_api_db_facet');
$select
->addMetaData('search_api_query', $query);
$select
->addMetaData('search_api_db_fields', $fields);
$select
->addMetaData('search_api_db_facet', $facet);
// If "Include missing facet" is disabled, we use an INNER JOIN and add
// IS NOT NULL for shared tables.
$is_text_type = search_api_is_text_type($field['type']);
$alias = $this
->getTableAlias($field, $select, TRUE, $facet['missing'] ? 'leftJoin' : 'innerJoin');
$select
->addField($alias, $field['column'], 'value');
if ($is_text_type) {
$select
->condition("{$alias}.field_name", $this
->getTextFieldName($facet['field']));
}
if (!$facet['missing'] && !$is_text_type) {
$select
->isNotNull($alias . '.' . $field['column']);
}
$select
->addExpression('COUNT(DISTINCT t.item_id)', 'num');
$select
->groupBy('value');
$select
->orderBy('num', 'DESC');
$limit = $facet['limit'];
if ((int) $limit > 0) {
$select
->range(0, $limit);
}
if ($facet['min_count'] > 1) {
$select
->having('COUNT(DISTINCT t.item_id) >= :count', array(
':count' => $facet['min_count'],
));
}
$terms = array();
$values = array();
$has_missing = FALSE;
foreach ($select
->execute() as $row) {
$terms[] = array(
'count' => $row->num,
'filter' => isset($row->value) ? '"' . $row->value . '"' : '!',
);
if (isset($row->value)) {
$values[] = $row->value;
}
else {
$has_missing = TRUE;
}
}
// If 'Minimum facet count' is set to 0 in the display options for this
// facet, we need to retrieve all facets, even ones that aren't matched
// in our search result set above. Here we SELECT all DISTINCT facets,
// and add in those facets that weren't added above.
if ($facet['min_count'] < 1) {
$select = $this->connection
->select($field['table'], 't');
$select
->addField('t', $field['column'], 'value');
$select
->distinct();
if ($values) {
$select
->condition($field['column'], $values, 'NOT IN');
}
if ($is_text_type) {
$select
->condition('t.field_name', $this
->getTextFieldName($facet['field']));
}
else {
$select
->isNotNull($field['column']);
}
// Add tags and metadata.
$select
->addTag('search_api_db_facet_all');
$select
->addMetaData('search_api_query', $query);
$select
->addMetaData('search_api_db_fields', $fields);
$select
->addMetaData('search_api_db_facet', $facet);
foreach ($select
->execute() as $row) {
$terms[] = array(
'count' => 0,
'filter' => '"' . $row->value . '"',
);
}
if ($facet['missing'] && !$has_missing) {
$terms[] = array(
'count' => 0,
'filter' => '!',
);
}
}
$ret[$key] = $terms;
}
return $ret;
} catch (PDOException $e) {
watchdog_exception('search_api_db', $e, '%type while trying to calculate facets: !message in %function (line %line of %file).');
return array();
}
}