在我目前的应用程序中,我使用hibernate搜索来索引和搜索数据。它工作正常。但是在构建服务器实例集群时,我不需要使用JMS或JGroups来使用主从集群。
所以我试图将hibernate搜索与apache solr集成。我关注了this example。
并做了一些小修改,与新的apache.lucene.core版本兼容。
public class HibernateSearchSolrWorkerBackend implements BackendQueueProcessor {
private static final String ID_FIELD_NAME = "id";
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
private ConcurrentUpdateSolrClient solrServer;
@Override
public void initialize(Properties properties, WorkerBuildContext workerBuildContext, DirectoryBasedIndexManager directoryBasedIndexManager) {
solrServer = new ConcurrentUpdateSolrClient("http://localhost:8983/solr/test", 20, 4);
}
@Override
public void close() {
}
@Override
public void applyWork(List<LuceneWork> luceneWorks, IndexingMonitor indexingMonitor) {
List<SolrInputDocument> solrWorks = new ArrayList<>(luceneWorks.size());
List<String> documentsForDeletion = new ArrayList<>();
for (LuceneWork work : luceneWorks) {
SolrInputDocument solrWork = new SolrInputDocument();
if (work instanceof AddLuceneWork) {
handleAddLuceneWork((AddLuceneWork) work, solrWork);
} else if (work instanceof UpdateLuceneWork) {
handleUpdateLuceneWork((UpdateLuceneWork) work, solrWork);
} else if (work instanceof DeleteLuceneWork) {
documentsForDeletion.add(((DeleteLuceneWork)work).getIdInString());
} else {
throw new RuntimeException("Encountered unsupported lucene work " + work);
}
solrWorks.add(solrWork);
}
try {
deleteDocs(documentsForDeletion);
solrServer.add(solrWorks);
softCommit();
} catch (SolrServerException | IOException e) {
throw new RuntimeException("Failed to update solr", e);
}
}
@Override
public void applyStreamWork(LuceneWork luceneWork, IndexingMonitor indexingMonitor) {
throw new RuntimeException("HibernateSearchSolrWorkerBackend.applyStreamWork isn't implemented");
}
@Override
public Lock getExclusiveWriteLock() {
return writeLock;
}
@Override
public void indexMappingChanged() {
}
private void deleteDocs(Collection<String> collection) throws IOException, SolrServerException {
if (collection.size()>0) {
StringBuilder stringBuilder = new StringBuilder(collection.size()*10);
stringBuilder.append(ID_FIELD_NAME).append(":(");
boolean first=true;
for (String id : collection) {
if (!first) {
stringBuilder.append(',');
}
else {
first=false;
}
stringBuilder.append(id);
}
stringBuilder.append(')');
solrServer.deleteByQuery(stringBuilder.toString());
}
}
private void copyFields(Document document, SolrInputDocument solrInputDocument) {
boolean addedId = false;
for (IndexableField fieldable : document.getFields()) {
if (fieldable.name().equals(ID_FIELD_NAME)) {
if (addedId)
continue;
else
addedId = true;
}
solrInputDocument.addField(fieldable.name(), fieldable.stringValue());
}
}
private void handleAddLuceneWork(AddLuceneWork luceneWork, SolrInputDocument solrWork) {
copyFields(luceneWork.getDocument(), solrWork);
}
private void handleUpdateLuceneWork(UpdateLuceneWork luceneWork, SolrInputDocument solrWork) {
copyFields(luceneWork.getDocument(), solrWork);
}
private void softCommit() throws IOException, SolrServerException {
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.setParam("soft-commit", "true");
updateRequest.setAction(UpdateRequest.ACTION.COMMIT,false, false);
updateRequest.process(solrServer);
}
}
将Hibernate属性设置为
<persistence-unit name="JPAUnit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>search.domain.Book</class>
<properties>
<property name="hibernate.search.default.directory_provider" value="filesystem"/>
<property name="hibernate.search.default.worker.backend" value="search.adapter.HibernateSearchSolrWorkerBackend"/>
</properties>
</persistence-unit>
并尝试使用以下测试方法
索引文档@Test
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Rollback(false)
public void saveBooks() {
Book bk1 = new Book(1L, "book1", "book1 description", 100.0);
Book bk2 = new Book(2L, "book2", "book2 description", 100.0);
bookRepository.save(bk1);
bookRepository.save(bk2);
}
这会将记录保存到数据库。如果我删除
<property name="hibernate.search.default.worker.backend" value="search.adapter.HibernateSearchSolrWorkerBackend"/>
并在配置文件中为hibernate搜索提供索引位置,它正确创建索引并成功执行搜索。但是当我将自定义工作者后端添加为apache solr时,它不会在apache solr核心数据文件夹中创建任何索引。