Статьи

Настройте Solr и запустите его


Что такое
Solr ? Lucene, но сделано правильно и на стероидах. Официальное определение:


Solr — популярная, быстро развивающаяся корпоративная поисковая платформа с открытым исходным кодом из проекта Apache Lucene.
Его основные функции включают мощный полнотекстовый поиск, выделение совпадений, граненый поиск, динамическую кластеризацию, интеграцию базы данных и обработку документов (например, Word, PDF). Solr обладает высокой масштабируемостью, обеспечивает распределенный поиск и репликацию индексов, а также поддерживает функции поиска и навигации на многих крупнейших мировых интернет-сайтах.

Основным свойством Solr (или, по крайней мере, самым полезным) является его REST-подобный Api, поскольку вместо игры с Api и драйверами для общения с Solr вы можете легко отправлять HTTP-запросы и получать результаты в JSON или XML (и это произносится солнечная , если вам интересно.)

Я бы не сказал, что это идеальный интерфейс REST, который воплощает в себе все принципы HTTP 1.1, но дело в том, что данные имеют простое представление, которое передается от клиента к серверу и обратно, и не содержат инкапсуляции в кошмарных оболочках SOAP. Кроме того, он удобочитаем, поскольку XML и JSON могут быть легко написаны для целей исследовательского тестирования.

Год назад, когда я услышал, что CouchDB имеет REST API, я сказал, что это бесполезный уровень абстракции, почему я не могу просто использовать расширение / драйвер PHP, как в MySQL, sqlite и подобных базах данных?

Теперь я вижу потенциал такого универсального интерфейса:

  • это не зависит от языка из-за использования XML или JSON, что в настоящее время может интерпретироваться почти всем. Метрикой обычно является JavaScript: если вы можете понять его на JavaScript в браузере со всеми его ограничениями, вы можете сделать это везде. Конечно, JavaScript изначально поддерживает как JSON (посредством eval (), даже если это небезопасно), так и XML (с DOM).
  • это не зависит от типа данных из-за HTTP, который может передавать только строки. Там нет безопасности типа, но большая совместимость. Динамические языки, такие как PHP, также очень успешны, потому что базовый протокол не имеет строгих типов. Если интерфейс только собирается его напечатать, почему строки не должно быть достаточно?
  • это более или менее стандартный протокол (хотя представление данных — нет): если кто-то, кто изобрел базу данных, публикует свой собственный двоичный протокол связи, у нас будет намного больше библиотек.

Solr написан на Java, но вы можете получить к нему доступ на любом языке по вашему выбору, просто выполняя запросы GET для поиска в индексе и запросы POST для добавления документов.

Конечно, обычно есть библиотека для каждого известного языка программирования, которая оборачивает REST-подобный интерфейс, но создать такую ​​библиотеку, например, с помощью JavaScript, очень просто, и совсем не обязательно использовать библиотеку. И это привело нас к другому вопросу: если бы у Solr был бинарный интерфейс, такой как у MySQL, как бы вы обернули это Javascript? HTTP универсален, так как теперь почти все, от компьютеров до духовок и фенов, может отправлять HTTP-запросы.

Начинающийся

Простота использования, начиная с протокола, является ключевой функцией по сравнению с Lucene, и действительно очень легко настроить Solr и запустить его.

Поскольку основной интерфейс Solr является веб-интерфейсом, ему нужен контейнер сервлета (изобретать колесо и реализовывать полный стек HTTP не было хорошей идеей). У Solr есть несколько сервлетов, которые обрабатывают разные конечные точки, такие как / update или / select.

Тем не менее, он поставляется с готовым примером с Jetty (небольшим, легким контейнером сервлетов), так что он запускается из коробки, но вы можете развернуть его также как веб-приложение Tomcat, если хотите.

Все, что вам нужно для запуска Solr — это распаковать релиз , перейдя в папку example / и запустив ‘java -jar start.jar’. Затем вы можете опубликовать образцы документов и сделать несколько запросов для пробного тестирования.

Конечно, связанная схема является примером, поэтому вы можете быстро изменить schema.xml для создания собственной схемы . Просто добавьте несколько тегов <field>:

   <field name="id" type="string" indexed="true" stored="true" required="true" /> 

<field name="PageTitle" type="string" indexed="true" stored="true"/>
<field name="Artist" type="string" indexed="true" stored="true"/>
<field name="Title" type="string" indexed="true" stored="true"/>

Автоматизация испытаний с индексом Solr

Поскольку Solr очень прост в использовании, давайте сделаем что-то страшное: автоматизация тестирования.

Когда я начал интегрировать Solr в свой проект приложения для поиска мультимедиа, я написал интеграционный тест с JUnit и классом SolrWrapper менее чем за два pomodoros , время, которое в основном пошло на изучение Api SolrJ, библиотеки Java, которая обертывает основанную на HTTP интерфейс. Я мог бы также сделать это просто с помощью URL и нативных объектов HttpURLConnection, если бы у меня не было библиотеки.

package it.polimi.chansonnier.test;

import java.util.ArrayList;
import java.util.Collection;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;


import junit.framework.TestCase;

public class SolrIntegrationTest extends TestCase {
private SolrWrapper solrWrapper;

public void testSolrInstanceCanBeStartedQueriedAndStopped() throws Exception {
solrWrapper = new SolrWrapper();
solrWrapper.start();

String url = "http://localhost:8983/solr";
CommonsHttpSolrServer server = new CommonsHttpSolrServer( url );
server.setParser(new XMLResponseParser());
server.deleteByQuery( "*:*" );// delete everything!
SolrInputDocument doc1 = new SolrInputDocument();
doc1.addField( "id", "id1", 1.0f );
doc1.addField( "name", "doc1", 1.0f );
Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
docs.add( doc1 );
server.add( docs );
server.commit();

SolrQuery query = new SolrQuery();
query.setQuery( "*:*" );
//query.addSortField( "name", SolrQuery.ORDER.asc );
QueryResponse rsp = server.query( query );
SolrDocumentList docList = rsp.getResults();
assertEquals("[id1, doc1]", docList.get(0).values().toString());
}

public void tearDown() {
solrWrapper.stop();
}
}
package it.polimi.chansonnier.test;

import java.io.File;

public class SolrWrapper {
private Process solr;

public void start() throws Exception {
Runtime r = Runtime.getRuntime();
solr = r.exec("/usr/bin/java -jar start.jar", null, getSolrRoot());
Thread.sleep(5000);
}

public void stop() {
if (solr != null) {
solr.destroy();
}
}

private File getSolrRoot() throws Exception {
String root = System.getProperty("it.polimi.chansonnier.solr.root");
if (root == null) {
throw new Exception("Solr path is not specified, please add the property it.polimi.chansonnier.solr.root");
}
return new File(root);
}
}

Помните, что интеграционный тест по моему определению (и растущему объектно-ориентированному программному обеспечению ) включает только поведение внешнего объекта, чтобы убедиться, что мы понимаем, как он работает, и что контракт, к которому мы программируем в нашем коде, является правильным.

Теперь мои приемочные тесты запускают Solr и останавливают его в конце теста, сбрасывая его индекс в начале каждого метода теста:

package it.polimi.chansonnier.test;

import java.io.IOException;

import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;

import junit.framework.TestCase;

public abstract class AcceptanceTest extends TestCase {
private SolrWrapper solrWrapper;
protected CommonsHttpSolrServer solrServer;

public void setUp() {
solrWrapper = new SolrWrapper();
try {
solrWrapper.start();
String url = "http://localhost:8983/solr";
solrServer = new CommonsHttpSolrServer( url );
solrServer.setParser(new XMLResponseParser());
solrServer.deleteByQuery( "*:*" );
} catch (Exception e) {
e.printStackTrace();
}
}

public void tearDown() {
solrWrapper.stop();
}
}

Что теперь?

Теперь, когда у меня есть запущенный экземпляр Solr для моего приложения, я планирую использовать AJAX Solr , библиотеку JavaScript, которая отправляет запросы непосредственно в Solr, для создания расширенного интерфейса. AJAX Solr является доказательством того, что браузеры стали мощными сегодня: вы действительно можете видеть, как он выполняет запросы через Firebug (представьте, что вы делаете это с реляционными базами данных в качестве серверной части).

Я всегда боялся приложений с расширенными возможностями из-за сложности тестирования, но теперь инструменты для этого выросли. Конечно, я протестирую свой веб-интерфейс с помощью HttpUnit, как и с обычным HTML; он использует Rhino для сканирования страниц на основе JavaScript и утверждает, что они сгенерированы правильно.