public function FuzzySearchService::search in Fuzzy Search 7
Executes a search on the server represented by this object.
Parameters
$query: The SearchApiQueryInterface object to execute.
Return value
array An associative array containing the search results, as required by SearchApiQueryInterface::execute().
Throws
SearchApiException If an error prevented the search from completing.
Overrides SearchApiServiceInterface::search
File
- includes/
service.inc, line 665
Class
- FuzzySearchService
- Search service class using the database for storing index information.
Code
public function search(SearchApiQueryInterface $query) {
$time_method_called = microtime(TRUE);
$set = $this
->setDb();
$index = $query
->getIndex();
if (empty($this->options['indexes'][$index->machine_name])) {
throw new SearchApiException(t('Unknown index !id.', array(
'!id' => $index->machine_name,
)));
}
$fuzzy = fuzzysearch_get_index_options($index);
$fields = $this->options['indexes'][$index->machine_name];
$keys =& $query
->getKeys();
$keys_set = (bool) $keys;
$keys = $this
->prepareKeys($keys);
if ($keys && !(is_array($keys) && count($keys) == 1)) {
$fulltext_fields = $query
->getFields();
if ($fulltext_fields) {
$_fulltext_fields = $fulltext_fields;
$fulltext_fields = array();
foreach ($_fulltext_fields as $name) {
if (!isset($fields[$name])) {
throw new SearchApiException(t('Unknown field !field specified as search target.', array(
'!field' => $name,
)));
}
if (!search_api_is_text_type($fields[$name]['type'])) {
throw new SearchApiException(t('Cannot perform fulltext search on field !field of type !type.', array(
'!field' => $name,
'!type' => $fields[$name]['type'],
)));
}
$fulltext_fields[$name] = $fields[$name];
}
$db_query = $this
->createKeysQuery($keys, $fulltext_fields, $fields, $fuzzy);
if (is_array($keys) && !empty($keys['#negation'])) {
$db_query
->addExpression(':score', 'score', array(
':score' => 1,
));
}
}
else {
$msg = t('Search keys are given but no fulltext fields are defined.');
watchdog('search api', $msg, NULL, WATCHDOG_WARNING);
$this->warnings[$msg] = 1;
}
}
elseif ($keys_set) {
$msg = t('No valid search keys were present in the query.');
$this->warnings[$msg] = 1;
$results = array(
'result count' => 0,
'results' => array(),
);
$results['warnings'] = array_keys($this->warnings);
$results['ignored'] = array_keys($this->ignored);
return $results;
}
$filter = $query
->getFilter();
if ($filter
->getFilters()) {
if (!isset($db_query)) {
$db_query = db_select($fields['search_api_language']['table'], 't', $this->queryOptions);
$db_query
->addField('t', 'item_id', 'item_id');
$db_query
->addExpression(':score', 'score', array(
':score' => 1,
));
}
$condition = $this
->createFilterCondition($filter, $fields, $db_query);
if ($condition) {
$db_query
->condition($condition);
}
}
if (!isset($db_query)) {
$db_query = db_select($fields['search_api_language']['table'], 't', $this->queryOptions);
$db_query
->addField('t', 'item_id', 'item_id');
$db_query
->addExpression(':score', 'score', array(
':score' => 1,
));
}
$time_processing_done = microtime(TRUE);
$results = array();
$count_query = $db_query
->countQuery();
// See @todo below.
$results['result count'] = $count_query
->execute()
->fetchField();
if ($results['result count']) {
if ($query
->getOption('search_api_facets')) {
$results['search_api_facets'] = $this
->getFacets($query, clone $db_query);
}
$query_options = $query
->getOptions();
if (isset($query_options['offset']) || isset($query_options['limit'])) {
$offset = isset($query_options['offset']) ? $query_options['offset'] : 0;
$limit = isset($query_options['limit']) ? $query_options['limit'] : 1000000;
$db_query
->range($offset, $limit);
}
$sort = $query
->getSort();
if ($sort) {
foreach ($sort as $field_name => $order) {
if ($order != 'ASC' && $order != 'DESC') {
$msg = t('Unknown sort order !order. Assuming "ASC".', array(
'!order' => $order,
));
$this->warnings[$msg] = $msg;
$order = 'ASC';
}
if ($field_name == 'search_api_relevance') {
$db_query
->orderBy('score', $order);
continue;
}
if ($field_name == 'search_api_id') {
$db_query
->orderBy('item_id', $order);
continue;
}
if (!isset($fields[$field_name])) {
throw new SearchApiException(t('Trying to sort on unknown field !field.', array(
'!field' => $field_name,
)));
}
$field = $fields[$field_name];
if (search_api_is_list_type($field['type'])) {
throw new SearchApiException(t('Cannot sort on field !field of a list type.', array(
'!field' => $field_name,
)));
}
if (search_api_is_text_type($field['type'])) {
throw new SearchApiException(t('Cannot sort on fulltext field !field.', array(
'!field' => $field_name,
)));
}
$alias = $this
->getTableAlias($field, $db_query);
$db_query
->orderBy($alias . '.value', $order);
}
}
else {
// If there isn't a "percent" alias already, see if we can find the
// completeness field to add the expression.
if (($expressions = $db_query
->getExpressions()) != FALSE && !array_key_exists('percent', $expressions)) {
foreach ($db_query
->getTables() as $alias => $tdata) {
if (isset($tdata['table']) && is_string($tdata['table']) && db_field_exists($tdata['table'], 'completeness')) {
$db_query
->addExpression('SUM(t.completeness)', 'percent');
}
}
}
// Check for the expression before attempting to sort by it.
if (($expressions = $db_query
->getExpressions()) != FALSE && array_key_exists('percent', $expressions)) {
// If "sort by score" is selected, score before percent.
if ($fuzzy['sort_score']) {
$db_query
->orderBy('score', 'DESC');
$db_query
->orderBy('percent', 'DESC');
}
else {
$db_query
->orderBy('percent', 'DESC');
$db_query
->orderBy('score', 'DESC');
}
}
else {
$db_query
->orderBy('score', 'DESC');
}
}
$result = $db_query
->execute();
$time_queries_done = microtime(TRUE);
foreach ($result as $row) {
$results['results'][$row->item_id] = array(
'id' => $row->item_id,
'score' => $row->score,
// Have to check because in a views search we return results by
// default, even without keys.
'percent' => isset($row->percent) ? $row->percent : '',
);
}
}
else {
$time_queries_done = microtime(TRUE);
$results['results'] = array();
}
$results['result count'] = $count_query
->execute()
->fetchField();
$results['warnings'] = array_keys($this->warnings);
$results['ignored'] = array_keys($this->ignored);
if ($set) {
$this
->resetDb();
}
$time_end = microtime(TRUE);
$results['performance'] = array(
'complete' => $time_end - $time_method_called,
'preprocessing' => $time_processing_done - $time_method_called,
'execution' => $time_queries_done - $time_processing_done,
'postprocessing' => $time_end - $time_queries_done,
);
return $results;
}