Статьи

Использование Solarium с SOLR для поиска — Solarium и GUI

Это вторая статья в серии из четырех статей об использовании Solarium в сочетании с поисковой реализацией Apache SOLR.

В первой части я представил ключевые концепции, и мы установили и настроили SOLR. Во второй части мы установим Solarium, начнем создавать пример приложения, заполним поисковый индекс и перейдем к позиции, с которой мы сможем начать поиск.

Создание приложения

Создайте новое приложение Laravel через Composer:

composer create-project laravel/laravel movie-search --prefer-dist 

Сделайте каталог app/storage каталог доступным для записи.

Установка солярия

Из первой части вы помните, что проект Solarium обеспечивает уровень абстракции по отношению к базовым запросам SOLR, что позволяет вам кодировать, как если бы SOLR был собственной реализацией поиска, работающей локально, вместо того, чтобы беспокоиться о выдаче HTTP-запросов или разборе ответов.

Безусловно, лучший способ установить Solarium — использовать Composer:

 "solarium/solarium": "dev-develop" 

Кроме того, вы можете скачать или клонировать его с Github .

Если вы следите и создаете приложение для поиска фильмов, оно будет помещено в файл composer.json вашего недавно созданного проекта, как и любой другой сторонний пакет; в этом случае нет поставщика услуг Laravel.

Настройка солярия

Конструктор клиента app/config/solr.php принимает массив сведений о соединении, поэтому создайте файл конфигурации — app/config/solr.php следующим образом:

 return array( 'host' => '127.0.0.1', 'port' => 8983, 'path' => '/solr/', ): 

Если вы установили SOLR в соответствии с инструкциями в первой части, эти значения по умолчанию должны быть хорошими, хотя в некоторых случаях вам может потребоваться изменить номер порта.

Для простоты мы просто собираемся создать экземпляр клиента Solarium как свойство контроллера ( app/controllers/HomeController.php ):

      /** * @var The SOLR client. */ 
     protected  $client ; 

     /** * Constructor **/ 
     public   function  __construct () 
     { 
         // create a client instance $this -> client =   new  \Solarium\Client ( Config :: get ( 'solr' )); 
     } 

Обычно в Laravel вы создаете экземпляр в сервис-провайдере, привязанном к контейнеру IoC, но этот способ подойдет для довольно простого приложения.

Ping Queries

Запрос ping полезен для проверки того, что сервер SOLR работает и доступен, и, следовательно, это хорошее место для начала. Использовать Solarium очень просто, поэтому вы можете проверить, все ли работает, используя следующее:

 // create a ping query $ping =  $client -> createPing (); 

 // execute the ping query 
 try   { $result =  $client -> ping ( $ping ); 
 }   catch   ( Solarium \Exception $e )   { 
     // the SOLR server is inaccessible, do something 
 } 

Как показано в примере, недоступный экземпляр SOLR выдает исключение, поэтому вы можете действовать соответствующим образом, перехватывая его в этой точке.

Образец данных

Для целей этого урока мы собираемся создать простой поиск фильмов. Я создал CSV-файл, содержащий около 2000 фильмов с набором ключевых слов (например, «Пространство», «Ночь» и «Дом»), который вы можете загрузить, или, если вы хотите создать свой собственный, вы можете попробовать API Rotten Tomatoes . (В качестве отдельного, но связанного, IMDB делают свои данные доступными, но распространяются на несколько файлов CSV, некоторые из которых огромны, и делают их доступными только через веб-сайт или через FTP.)

Прежде чем написать команду для импорта этих данных, давайте рассмотрим основные операции создания , обновления и удаления в реализации поиска SOLR с использованием Solarium.

Добавление документов в поисковый индекс

Чтобы добавить документ в поисковый индекс, сначала необходимо создать экземпляр запроса на обновление:

 $update = $client->createUpdate(); 

Затем создайте документ:

 $doc = $update->createDocument(); 

Теперь вы можете обрабатывать документ ( $doc ) так, как если бы он был stdClass и просто назначать данные как открытые свойства:

 $doc->id = 123; $doc->title = 'Some Movie'; $doc->cast = array('Sylvester Stallone', 'Marylin Monroe', 'Macauley Culkin'); 

… И так далее, перед добавлением документа в запрос на обновление:

 $update->addDocument($doc); 

Затем зафиксируйте обновление:

 $update->addCommit(); 

Наконец, чтобы запустить запрос, вы вызываете update() на клиенте:

 $result = $client->update($update); 

Если вы хотите убедиться, что вы успешно проиндексировали некоторые документы, зайдите в админ-панель SOLR в своем браузере — обычно это http://localhost:8983/solr и нажмите Core Admin, вы найдете количество документов в списке, указанном в списке. как numDocs в разделе Index .

Обновление документов

Если вам нужно обновить документ в индексе, вам просто нужно «повторно добавить» его и — если он имеет тот же уникальный идентификатор — SOLR будет достаточно умен, чтобы обновить его, а не добавлять новый.

Удаление документов

Вы можете удалить документ из индекса, используя запрос на обновление, используя синтаксис, не слишком отличающийся от предложений WHERE в SQL. Например, чтобы удалить документ, однозначно идентифицируемый идентификатором 123:

 // get an update query instance $update = $client->createUpdate(); // add the delete query and a commit command to the update query $update->addDeleteQuery('id:123'); $update->addCommit(); // this executes the query and returns the result $result = $client->update($update); 

Или вы можете быть менее конкретным:

 // get an update query instance $update = $client->createUpdate(); // add the delete query and a commit command to the update query $update->addDeleteQuery('title:test*'); $update->addCommit(); // this executes the query and returns the result $result = $client->update($update); 

Обратите внимание на использование подстановочного знака — другими словами: «удалить все документы, заголовок которых начинается с теста».

Заполнение поискового индекса фильмами

Теперь мы рассмотрели основы индексации документов, давайте поместим некоторые данные в индекс для нашего примера приложения.

Laravel облегчает создание консольных команд, поэтому давайте создадим одну для импорта содержимого нашего CSV-файла фильма и индексирования их. Мы также могли бы создать соответствующие записи базы данных на этом этапе, но для целей этого упражнения проиндексированные документы будут содержать все, что нам нужно.

Чтобы создать команду, введите в командной строке следующее:

 php artisan command:make PopulateSearchIndexCommand 

Во вновь созданном файле — app/commands/PopulateSearchIndexCommand.php — задайте имя команды (т. Е. То, что вы вводите в командной строке для ее запуска) и описание:

 /** * The console command name. * * @var string */ protected $name = 'search:populate'; /** * The console command description. * * @var string */ protected $description = 'Populates the search index with some sample movie data.'; 

Теперь мы будем использовать метод fire() для создания клиента Solarium, открытия CSV, итерации по нему и индексации каждого фильма:

 /** * Execute the console command. * * @return void */ public function fire() { $client = new \Solarium\Client(Config::get('solr')); // open up the CSV $csv_filepath = storage_path() . '/movies.csv'; $fp = fopen($csv_filepath, 'r'); // Now let's start importing while (($row = fgetcsv($fp, 1000, ";")) !== FALSE) { // get an update query instance $update = $client->createUpdate(); // Create a document $doc = $update->createDocument(); // set the ID $doc->id = $row[0]; // ..and the title $doc->title = $row[1]; // The year, rating and runtime columns don't always have data if (strlen($row[2])) { $doc->year = $row[2]; } if (strlen($row[3])) { $doc->rating = $row[3]; } if (strlen($row[4])) { $doc->runtime = $row[4]; } // set the synopsis $doc->synopsis = $row[5]; // We need to create an array of cast members $cast = array(); // Rows 6 through 10 contain (or don't contain) cast members' names for ($i = 6; $i <= 10; $i++) { if ((isset($row[$i])) && (strlen($row[$i]))) { $cast[] = $row[$i]; } } // ...then we can assign the cast member array to the document $doc->cast = $cast; // Let's simply add and commit straight away. $update->addDocument($doc); $update->addCommit(); // this executes the query and returns the result $result = $client->update($update); } fclose($fp); } 

Хотя это не самый тонкий и гибкий код, это довольно академическое упражнение, которое мы планируем выполнить только один раз. Убедитесь, что файл CSV находится в правильном месте — app/storage/movies.csv и запустите его:

 php artisan search:populate 

Все хорошо, индекс теперь должен содержать ~ 2300 фильмов. Вы можете проверить это через интерфейс администратора.

В следующем разделе мы начнем строить основной поиск в.

Форма поиска

Давайте создадим форму поиска, используя шаблонизатор Laravel’s Blade , вместе с конструктором форм . Итак, в app/views/home/index.blade.php :

 @extends('layouts.default') @section('content') <header> {{ Form::open(array('method' => 'GET')) }} <div class="input-group"> {{ Form::text('q', Input::get('q'), array('class' => 'form-control input-lg', 'placeholder' => 'Enter your search term')) }} <span class="input-group-btn"> {{ Form::submit('Search', array('class' => 'btn btn-primary btn-lg')) }} </span> </div> {{ Form::close() }} </header> @endsection 

Базовый макет страницы в app/views/layouts/default.blade.php :

 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Movie Search</title> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css"> </head> <body> <div class="container"> <header id="header" class="row"> <div class="col-sm-12 col-md-12 col-lg-12"> <h1>Movie Search</h1> </div> </header> <div class="row"> <div class="col-sm-12 col-md-12 col-lg-12"> @yield('content') </div> </div> <hr /> <footer id="footer"> </footer> </div> </body> </html> 

В app/controllers/HomeController.php :

 public function getIndex() { return View::make('home.index'); } 

Наконец, замените содержимое app/routes.php следующим, чтобы Laravel сказал использовать HomeController :

 <?php /* |-------------------------------------------------------------------------- | Application Routes |-------------------------------------------------------------------------- */ Route::controller('/', 'HomeController'); 

Теперь мы настроены и готовы реализовать базовый механизм поиска, который станет темой следующей части серии.

Резюме

Во второй части серии из четырех частей мы установили Solarium с целью интеграции SOLR в Apache с приложением PHP. Мы создали пример приложения и проиндексировали некоторые данные. В следующей части мы начнем реализацию поискового механизма.