예제 #1
0
 /**
  * Tests the processor's preprocessSearchQuery() method.
  */
 public function testPreprocessSearchQuery()
 {
     $index = $this->getMock('Drupal\\search_api\\IndexInterface');
     $index->expects($this->any())->method('status')->will($this->returnValue(TRUE));
     /** @var \Drupal\search_api\IndexInterface $index */
     $this->processor->setIndex($index);
     $query = Utility::createQuery($index);
     $keys = array('#conjunction' => 'AND', 'foo', 'bar', 'bar foo');
     $query->keys($keys);
     $this->processor->setConfiguration(array('stopwords' => array('foobar', 'bar', 'barfoo')));
     $this->processor->preprocessSearchQuery($query);
     unset($keys[1]);
     $this->assertEquals($keys, $query->getKeys());
     $results = Utility::createSearchResultSet($query);
     $this->processor->postprocessSearchResults($results);
     $this->assertEquals(array('bar'), $results->getIgnoredSearchKeys());
 }
예제 #2
0
 /**
  * {@inheritdoc}
  */
 public function search(QueryInterface $query)
 {
     $this->checkError(__FUNCTION__);
     $results = Utility::createSearchResultSet($query);
     $result_items = array();
     $datasources = $query->getIndex()->getDatasources();
     /** @var \Drupal\search_api\Datasource\DatasourceInterface $datasource */
     $datasource = reset($datasources);
     $datasource_id = $datasource->getPluginId();
     if ($query->getKeys() && $query->getKeys()[0] == 'test') {
         $item_id = Utility::createCombinedId($datasource_id, '1');
         $item = Utility::createItem($query->getIndex(), $item_id, $datasource);
         $item->setScore(2);
         $item->setExcerpt('test');
         $result_items[$item_id] = $item;
     } elseif ($query->getOption('search_api_mlt')) {
         $item_id = Utility::createCombinedId($datasource_id, '2');
         $item = Utility::createItem($query->getIndex(), $item_id, $datasource);
         $item->setScore(2);
         $item->setExcerpt('test test');
         $result_items[$item_id] = $item;
     } else {
         $item_id = Utility::createCombinedId($datasource_id, '1');
         $item = Utility::createItem($query->getIndex(), $item_id, $datasource);
         $item->setScore(1);
         $result_items[$item_id] = $item;
         $item_id = Utility::createCombinedId($datasource_id, '2');
         $item = Utility::createItem($query->getIndex(), $item_id, $datasource);
         $item->setScore(1);
         $result_items[$item_id] = $item;
     }
     $results->setResultCount(count($result_items));
     return $results;
 }
예제 #3
0
 /**
  * Tests field highlighting and excerpts with two items.
  */
 public function testPostprocessSearchResultsWithTwoItems()
 {
     $query = $this->getMock('Drupal\\search_api\\Query\\QueryInterface');
     $query->expects($this->atLeastOnce())->method('getKeys')->will($this->returnValue(array('#conjunction' => 'OR', 'foo')));
     /** @var \Drupal\search_api\Query\QueryInterface $query */
     /** @var \Drupal\search_api\IndexInterface|\PHPUnit_Framework_MockObject_MockObject $index */
     $index = $this->getMock('Drupal\\search_api\\IndexInterface');
     $body_field = Utility::createField($index, 'body');
     $body_field->setType('text');
     $body_field->setDatasourceId('entity:node');
     $body_field->setPropertyPath('body');
     $index->expects($this->atLeastOnce())->method('getFields')->will($this->returnValue(array('body' => $body_field)));
     $this->processor->setIndex($index);
     $body_values = array('Some foo value', 'foo bar');
     $fields = array('entity:node/body' => array('type' => 'text', 'values' => $body_values));
     $items = $this->createItems($index, 2, $fields);
     $items[$this->itemIds[1]]->getField('body')->setValues(array('The second item also contains foo in its body.'));
     $results = Utility::createSearchResultSet($query);
     $results->setResultItems($items);
     $results->setResultCount(1);
     $this->processor->postprocessSearchResults($results);
     $output = $results->getExtraData('highlighted_fields');
     $this->assertEquals('Some <strong>foo</strong> value', $output[$this->itemIds[0]]['body'][0], 'Highlighting is correctly applied to first body field value.');
     $this->assertEquals('<strong>foo</strong> bar', $output[$this->itemIds[0]]['body'][1], 'Highlighting is correctly applied to second body field value.');
     $this->assertEquals('The second item also contains <strong>foo</strong> in its body.', $output[$this->itemIds[1]]['body'][0], 'Highlighting is correctly applied to second item.');
     $excerpt1 = '… Some <strong>foo</strong> value … <strong>foo</strong> bar …';
     $excerpt2 = '… The second item also contains <strong>foo</strong> in its body. …';
     $this->assertEquals($excerpt1, $items[$this->itemIds[0]]->getExcerpt(), 'Correct excerpt created from two text fields.');
     $this->assertEquals($excerpt2, $items[$this->itemIds[1]]->getExcerpt(), 'Correct excerpt created for second item.');
 }
예제 #4
0
파일: Database.php 프로젝트: jkyto/agolf
  /**
   * {@inheritdoc}
   */
  public function search(QueryInterface $query) {
    $this->ignored = $this->warnings = array();
    $index = $query->getIndex();
    $db_info = $this->getIndexDbInfo($index);

    if (!isset($db_info['field_tables'])) {
      throw new SearchApiException(new FormattableMarkup('Unknown index @id.', array('@id' => $index->id())));
    }
    $fields = $this->getFieldInfo($index);

    $db_query = $this->createDbQuery($query, $fields);

    $results = Utility::createSearchResultSet($query);

    $skip_count = $query->getOption('skip result count');
    if (!$skip_count) {
      $count_query = $db_query->countQuery();
      $results->setResultCount($count_query->execute()->fetchField());
    }

    if ($skip_count || $results->getResultCount()) {
      if ($query->getOption('search_api_facets')) {
        $results->setExtraData('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->getSorts();
      if ($sort) {
        foreach ($sort as $field_name => $order) {
          if ($order != 'ASC' && $order != 'DESC') {
            $msg = $this->t('Unknown sort order @order. Assuming "ASC".', array('@order' => $order));
            $this->warnings[(string) $msg] = 1;
            $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(new FormattableMarkup('Trying to sort on unknown field @field.', array('@field' => $field_name)));
          }
          $alias = $this->getTableAlias(array('table' => $db_info['index_table']), $db_query);
          $db_query->orderBy($alias . '.' . $fields[$field_name]['column'], $order);
          // PostgreSQL automatically adds a field to the SELECT list when
          // sorting on it. Therefore, if we have aggregations present we also
          // have to add the field to the GROUP BY (since Drupal won't do it for
          // us). However, if no aggregations are present, a GROUP BY would lead
          // to another error. Therefore, we only add it if there is already a
          // GROUP BY.
          if ($db_query->getGroupBy()) {
            $db_query->groupBy($alias . '.' . $fields[$field_name]['column']);
          }
        }
      }
      else {
        $db_query->orderBy('score', 'DESC');
      }

      $result = $db_query->execute();

      foreach ($result as $row) {
        $item = Utility::createItem($index, $row->item_id);
        $item->setScore($row->score / self::SCORE_MULTIPLIER);
        $results->addResultItem($item);
      }
      if ($skip_count && !empty($item)) {
        $results->setResultCount(1);
      }
    }

    $results->setWarnings(array_keys($this->warnings));
    $results->setIgnoredSearchKeys(array_keys($this->ignored));

    return $results;
  }
예제 #5
0
 /**
  * Extract results from a Solr response.
  *
  * @param \Drupal\search_api\Query\QueryInterface $query
  *   The Search API query object.
  * @param \Solarium\Core\Query\Result\ResultInterface $result
  *   A Solarium select response object.
  *
  * @return \Drupal\search_api\Query\ResultSetInterface
  *   A result set object.
  */
 protected function extractResults(QueryInterface $query, ResultInterface $result)
 {
     $index = $query->getIndex();
     $field_names = $this->getFieldNames($index);
     $fields = $index->getFields();
     $site_hash = SearchApiSolrUtility::getSiteHash();
     // We can find the item ID and the score in the special 'search_api_*'
     // properties. Mappings are provided for these properties in
     // SearchApiSolrBackend::getFieldNames().
     $id_field = $field_names['search_api_id'];
     $score_field = $field_names['search_api_relevance'];
     // Set up the results array.
     $result_set = SearchApiUtility::createSearchResultSet($query);
     $result_set->setExtraData('search_api_solr_response', $result->getData());
     // In some rare cases (e.g., MLT query with nonexistent ID) the response
     // will be NULL.
     $is_grouping = $result instanceof Result && $result->getGrouping();
     if (!$result->getResponse() && !$is_grouping) {
         $result_set->setResultCount(0);
         return $result_set;
     }
     // If field collapsing has been enabled for this query, we need to process
     // the results differently.
     $grouping = $query->getOption('search_api_grouping');
     $docs = array();
     if (!empty($grouping['use_grouping']) && $is_grouping) {
         //      $docs = array();
         //      $result_set['result count'] = 0;
         //      foreach ($grouping['fields'] as $field) {
         //        if (!empty($response->grouped->{$fields[$field]})) {
         //          $result_set['result count'] += $response->grouped->{$fields[$field]}->ngroups;
         //          foreach ($response->grouped->{$fields[$field]}->groups as $group) {
         //            foreach ($group->doclist->docs as $doc) {
         //              $docs[] = $doc;
         //            }
         //          }
         //        }
         //      }
     } else {
         $result_set->setResultCount($result->getNumFound());
         $docs = $result->getDocuments();
     }
     // Add each search result to the results array.
     /** @var \Solarium\QueryType\Select\Result\Document $doc */
     foreach ($docs as $doc) {
         $doc_fields = $doc->getFields();
         $item_id = $doc_fields[$id_field];
         // For items coming from a different site, we need to adapt the item ID.
         if (!$this->configuration['site_hash'] && $doc_fields['hash'] != $site_hash) {
             $item_id = $doc_fields['hash'] . '--' . $item_id;
         }
         $result_item = SearchApiUtility::createItem($index, $item_id);
         $result_item->setScore($doc_fields[$score_field]);
         unset($doc_fields[$id_field], $doc_fields[$score_field]);
         // Extract properties from the Solr document, translating from Solr to
         // Search API property names. This reverses the mapping in
         // SearchApiSolrBackend::getFieldNames().
         foreach ($field_names as $search_api_property => $solr_property) {
             if (isset($doc_fields[$solr_property])) {
                 // Date fields need some special treatment to become valid date values
                 // (i.e., timestamps) again.
                 if (isset($fields[$search_api_property]) && $fields[$search_api_property]->getType() == 'date' && preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/', $doc_fields[$solr_property][0])) {
                     $doc_fields[$solr_property][0] = strtotime($doc_fields[$solr_property][0]);
                 }
                 $field = SearchApiUtility::createField($index, $search_api_property);
                 $field->setValues($doc_fields[$solr_property]);
                 $result_item->setField($search_api_property, $field);
             }
         }
         $index_id = $this->getIndexId($index->id());
         $solr_id = $this->createId($index_id, $result_item->getId());
         $item_fields = $result_item->getFields();
         $excerpt = $this->getSolrHelper()->getExcerpt($result->getData(), $solr_id, $item_fields, $field_names);
         if ($excerpt) {
             $result_item->setExcerpt($excerpt);
         }
         $result_set->addResultItem($result_item);
     }
     // Check for spellcheck suggestions.
     /*if (module_exists('search_api_spellcheck') && $query->getOption('search_api_spellcheck')) {
          $result_set->setExtraData('search_api_spellcheck', new SearchApiSpellcheckSolr($result));
       }*/
     return $result_set;
 }
 /**
  * {@inheritdoc}
  */
 public function search(QueryInterface $query)
 {
     // This plugin does not support searching and we therefore just return an empty search result.
     $results = Utility::createSearchResultSet($query);
     $results->setResultItems(array());
     $results->setResultCount(0);
     return $results;
 }