web-dev-qa-db-ja.com

プログラムで検索APIを使用する

このようなことをしたい

    $index = search_api_index_load("node_index");
    $myQuery=new SearchApiQuery($index);
    $myQuery->condition('type', 'blog', '=');
    $data=$myQuery->execute();
    $results=$data['results'];
    print_r($results);

Drupal 8の場合、検索APIを使用します。それは可能ですか?

6
José Trindade
$query = Index::load('my_index')->query();
$query->addCondition('search_api_language', $language);
$query->keys($search_string);
$query->range(0, 25);
$data = $query->execute();

また、結果のカスタム解析関数があります。

function parse_results(array $results) {
$list = [];
  foreach ($results AS $item) {
    // The pattern is "entity:[entity_type]:[entity_id]:[language_code]".
    // For example "entity:node/1:en".
    $data = explode(':', $item->getId());
    $data = explode('/', $data[1]);
    $list[] = $data[1];
  }
  return $list;
}
5
user21641

ここに私が数ヶ月前に取り組んでいたアイデアの要点があります。基本的に、カスタムモジュールにはルーター(/ searchなど)があり、これがそれを処理します。まだカスタム検索フォームを実装するところまでは移動していませんでしたが、結果のページの開始点とページャーに到達しました。

namespace Drupal\velirsearch\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\velirsearch\Service\PagerService;

class SearchResults extends ControllerBase {

  /**
   * @var \Drupal\velirsearch\Service\PagerService
   */
  private $pager_service;

  /**
   * SearchResults constructor.
   * @param \Drupal\velirsearch\Service\PagerService $pager_service
   */
  public function __construct(PagerService $pager_service) {
    $this->pager_service = $pager_service;
  }

  /**
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   * @return static
   */
  public static function create(ContainerInterface $container) {
    $pager_service = $container->get('velirsearch.pager_service');
    return new static($pager_service);
  }

  /**
   * @param \Symfony\Component\HttpFoundation\Request $request
   * @return array
   */
  public function build(Request $request) {
    /* @var $search_api_index \Drupal\search_api\IndexInterface */
    $index = $this->getSearchIndex('new_solr_test');

    // Create the query.
    $query = $index->query([
      'limit' => 10,
      'offset' => !is_null($request->get('page')) ? $request->get('page') * 10 : 0,
      'search id' => 'velirsearch:1',
    ]);

    if (!is_null($request->get('keyword'))) {
      $query->keys(['body' => $request->get('keyword'), '#conjunction' => 'AND']);
    }

    $results = $query->execute();

    $output = '';

    foreach ($results as $result) {
      $value = $result->getField('view_mode_teaser')->getValues();
      $output .= $value[0];
    }

    $render[] = [
      '#markup' => $output,
      '#type' => 'remote',
    ];

    $render[] = $this->attachPager($results->getResultCount(), 10);

    return $render;
  }

  /**
   * Title callback.
   *
   * @param Request $request
   *   The request.
   *
   * @return string $title
   *   The page title.
   */
  public function title(Request $request) {
    if (!is_null($request->get('keyword'))) {
      return $this->t('Search results for %keyword', ['%keyword' => $request->get('keyword')]);
    }

    return $this->t('Search results');
  }

  /**
   * Load and return a search index.
   * @param $id
   * @return \Drupal\Core\Entity\EntityInterface|null
   */
  protected function getSearchIndex($id) {
    return $this->entityTypeManager()->getStorage('search_api_index')->load($id);
  }

  /**
   * Convenient method to obtain a pager to attach from the pager service.
   * @param $totalRows
   * @param $limit
   * @return array
   */
  protected function attachPager($totalRows, $limit) {
    return $this->pager_service->getPager($totalRows, $limit);
  }
}

attachPagerメソッドは単に次を返します:

pager_default_initialize($totalRows, $limit);
return ['#type' => 'pager'];

古いページャーコードを複製せずに複数のカスタム検索を作成したい場合に備えて、それを分離していました。

また、結果としてSolrのレコードの値を単純に連結していることに注意してください。Solrにはビューモードのレンダリングを保存しています。同じことを行わない限り、それらをその場でレンダリングする必要があるでしょう。

これは、現在ではないバージョンのSearch API、YMMVでも行われました。しかし、それは私にとってはうまくいきました。

5
Kevin

公式ドキュメントはこちら: コードでの検索の実行

以下は、いくつかのサンプルコードを使用して、プログラムでSearch API検索を実行する方法を示しています。

$index = \Drupal\search_api\Entity\Index::load('INDEX_ID');
$query = $index->query();

// Change the parse mode for the search.
$parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')
  ->createInstance('direct');
$parse_mode->setConjunction('OR');
$query->setParseMode($parse_mode);

// Set fulltext search keywords and fields.
$query->keys('alea iacta');
$query->setFulltextFields(['title', 'name', 'body']);

// Set additional conditions.
$query->addCondition('status', 1)
  ->addCondition('author', 1, '<>');

// Add more complex conditions.
// (In this case, a condition for a specific datasource).
$time = \Drupal::service('datetime.time')->getRequestTime();
$conditions = $query->createConditionGroup('OR');
$conditions->addCondition('search_api_datasource', 'entity:node', '<>')
  ->addCondition('created', $time - 7 * 24 * 3600, '>=');

// Restrict the search to specific languages.
$query->setLanguages(['de', 'it']);

// Do paging.
$query->range(20, 10);

// Set additional options.
// (In this case, retrieve facets, if supported by the backend.)
$server = $index->getServerInstance();
if ($server->supportsFeature('search_api_facets')) {
  $query->setOption('search_api_facets', [
    'type' => [
      'field' => 'type',
      'limit' => 20,
      'operator' => 'AND',
      'min_count' => 1,
      'missing' => TRUE,
    ],
  ]);
}

// Set one or more tags for the query.
// @see hook_search_api_query_TAG_alter()
// @see hook_search_api_results_TAG_alter()
$query->addTag('custom_search');

// Execute the search.
$results = $query->execute();

echo "Result count: {$results->getResultCount()}\n";
$ids = implode(', ', array_keys($results->getResultItems()));
echo "Returned IDs: $ids.\n";
$facets = $results->getExtraData('search_api_facets', []);
echo 'Facets data: ' . var_export($facets, TRUE);
3
Tim Yao