пятница, 29 апреля 2016 г.

Интеграция Solr в ADF (Integration Solr in ADF)

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

В этой статье я хочу интегрировать поиск Solr в ADF. Я создам таблицу со 100 000 записями, проиндексирую их при помощи Solr а потом найду данные. Начнём.

1. Скачайте последнюю версию Solr(http://lucene.apache.org/solr/downloads.html). Сейчас это 6-ая версия. В скачанном архиве зайдите в папку bin и выполните команду:

solr start

После того как появится сообщение "Waiting up to 30 to see Solr running on port 8983
Started Solr server on port 8983. Happy searching!", вы можете зайти на запущенный сервер(если вы хотите, что бы сервер запустился не на 8983 порте,  используйте параметр -p. Например:  solr start -p 8984 ) :


http://localhost:8983/solr





Solr сервер запущен, теперь для индексации данных, нужно создать core. Для этого этого скопируйте с директории server/solr/configsets/basic_configs/conf файлы в директорию /server/solr/{имя создоваемого core}. После этого переименуйте файл managed-schema в schema.xml. В этом файле находится схема документа добавляемого в solr. Для работы со схемой в основном используются два тега : field - поле документа, fieldType - оперделение сложного типа поля(более подробное описание: http://www.solrtutorial.com/schema-xml.html) . В моем  случае я индексирую 3 поля(id,title и content). При добавлении полей, провеяйте не дублируются ли они:


<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="title" type="string" indexed="true" stored="true" multiValued="false"/>
<field name="content" type="string" indexed="true" stored="true" multiValued="false" />

После этого вернитесь в интерфейс, и создайте core :
                                        
где article_core имя создаваемого core

2. Далее если запущен Solr и у вас есть данные для индексации,  создайте Fusion Web Application. В созданном приложении во ViewController->Project Properties-> Lisbraries and Classpath  добавьте с директории dist файл solr-solrj-6.0.0.jar и все файлы с директории  dist\solrj-lib\ . После этого, в вашем проекте станет дотспуен SolrJ. SolrJ - это клиент для работы с Solr в Java(описание solrj на английском : https://cwiki.apache.org/confluence/display/solr/Using+SolrJ )



3.   После того как добавлены необходимые библиотеки, нужно проиндексировать данные. Для этого необходимо :
  •  соединиться с вашим core на Solr сервере: 
SolrClient solr =  new HttpSolrClient("http://localhost:8983/solr/article_core");
  • создать SolrInputDocument
                       SolrInputDocument doc = new SolrInputDocument();
  •  добавить необходимые значение в поля :
doc.addField("<название поля в Solr>", <значение>);
  •  добавить документ на сервер и сохранить его :
    solr.add(doc); solr.commit();
В моем случае получился следующий код:


public void indexData(ActionEvent actionEvent) { Date dateBegin = new Date(System.currentTimeMillis());
SolrClient solr;
try {
solr = new HttpSolrClient("http://localhost:8983/solr/article_core");
getAm().getArticlesView1().first();
for (int i = 0; i <= getAm().getArticlesView1().getEstimatedRowCount(); i++){
ArticlesViewRowImpl row =  (ArticlesViewRowImpl) getAm().getArticlesView1().getCurrentRow();
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", row.getId());
doc.addField("title", row.getTitle());
doc.addField("content", row.getContent());
solr.add(doc);
solr.commit();
getAm().getArticlesView1().next();
}
} catch (MalformedURLException e) {
logger.severe("MalformedURLException:"+e);
} catch (IOException e) {
logger.severe("IOException:"+e);
} catch (SolrServerException e) {
logger.severe("SolrServerException:"+e);
}
Date dateEnd = new Date(System.currentTimeMillis());
long indexTime = dateEnd.getTime() - dateBegin.getTime();
tookTime.setValue("index data tookTime:" + indexTime +" ms");
}




4.  После того как данные проиндексировались, можно совершить поиск. Для этого необходимо:

  •  соединиться с вашим core на Solr сервере: 
SolrClient solr = new HttpSolrClient("http://localhost:8983/solr/article_core");
  •  сформировать запрос, с необходимыми параметрами:
    SolrQuery query = new SolrQuery(); query.setQuery("content:"+queryString); //где "content:" -название поля, а queryString - искомая строка
    query.setRows(RECORDS_COUNT); // количество возвращаемых записей
  •  Получить ответ по запросу 
QueryResponse rsp = solr.query(query);
SolrDocumentList docs = rsp.getResults();

В моем случае получился следующий код:


public void solrSearch(ActionEvent actionEvent) {
Date dateBegin = new Date(System.currentTimeMillis());
logger.warning("content:" + content.getValue());
SolrClient solr;
String queryString = (String) (content.getValue() != null ? content.getValue() : "*:*");
logger.warning("queryString:" + queryString);
try {
solr = new HttpSolrClient("http://localhost:8983/solr/article_core");
SolrQuery query = new SolrQuery();
query.setQuery("content:"+queryString);
query.setRows(RECORDS_COUNT);
QueryResponse rsp = solr.query(query);
SolrDocumentList docs = rsp.getResults();
Date dateEnd = new Date(System.currentTimeMillis());
long searchTime = dateEnd.getTime() - dateBegin.getTime();
tookTime.setValue("solrSearch tookTime:" + searchTime + " found docs:" + docs.size());
for (int i = 0; i < docs.size(); i++) {
System.out.println(docs.get(i));
}
} catch (MalformedURLException e) {
logger.severe("MalformedURLException:"+e);
} catch (IOException e) {
logger.severe("IOException:"+e);
} catch (SolrServerException e) {
logger.severe("SolrServerException:"+e);
}


Исходники приложения на github: https://github.com/JealousyM/solr-adf