Solr在企业中的应用,多半是从数据库导入数据。
Solr在企业中的应用,多半是从数据库导入数据。而从数据库导入数据,最好的工具莫过于DataImportHandler,DIH的用法非常灵活,效率也很高。
关于DIH的基础配置,可以参考http://sbp810050504.blog.51cto.com/2799422/1182942
在DIH中,还有一些好玩的东西,比如:
一、增量索引。
尽管DIH中讲到delta-import可以进行增量索引,但是貌似效率不高(没有去考证)。其实用full-import也可以实现增量索引。
怎么实现呢。我们把目光关注到db-data-config.xml的<entity>节点上,在<entity>的query属性的值一般是select * from table。
当我们用http://localhost:8983/solr/dataimport?command=full-import来向索引中添加数据时,solr首先会清空索引。
如果我们用URL:
http://localhost:8983/solr/dataimport?command=full-import&clean=false
则不会清空索引。
然后我们在 <entity>配置如下
<entity name="table_name" query="select * from table_name where updatetime > ‘{dih.last_index_time}’">
这里唯一不方便的是需要数据库表中有一个update_time的字段。
现在我们把目光关注到dih.last_index_time 。这个东西在哪里呢?我们执行full-import后,在solrconfig.xml相同的目录下会生成一个文件dataimport.properties。在这个文件中记录着dih.last_index_time 的值。
这样就可以用dih进行增量式的索引了,如果我们在linux下写个例行性工作排程,则solr可以定时更新索引。是不是很方便?
二、导入符合条件的数据
好了,如果我们想从数据库中导入特定的数据,比如id=1001,比如update_time在2012到2013年之间的数据。该怎么做呢?
在不修改程序的前提下,solr提供了这样的功能。以导入id=1001的数据为例。
我们可以这样修改<entity>的query属性:
<entity name="table_name" query="select * from table_name where id= {dih.request.id}">
对了,关键点在于dih.request.id这个属性。
那么我们怎么把id传进去呢?当然是通过url:
http://localhost:8983/solr/dataimport?command=full-import&id=1001
是不是很简单?
在这些技巧其实通过看solr的源代码就能够了解到。在DocBuilder类的getVariableResolver方法中,代码如下:
public VariableResolverImpl getVariableResolver() {
try {
VariableResolverImpl resolver = null;
if(dataImporter != null && dataImporter.getCore() != null
&& dataImporter.getCore().getResourceLoader().getCoreProperties() != null){
resolver = new VariableResolverImpl(dataImporter.getCore().getResourceLoader().getCoreProperties());
} else resolver = new VariableResolverImpl();
Map<String, Object> indexerNamespace = new HashMap<String, Object>();
if (persistedProperties.getProperty(LAST_INDEX_TIME) != null) {
indexerNamespace.put(LAST_INDEX_TIME, persistedProperties.getProperty(LAST_INDEX_TIME));
} else {
// set epoch
indexerNamespace.put(LAST_INDEX_TIME, DataImporter.DATE_TIME_FORMAT.get().format(EPOCH));
}
indexerNamespace.put(INDEX_START_TIME, dataImporter.getIndexStartTime());
indexerNamespace.put("request", requestParameters.requestParams);
indexerNamespace.put("functions", functionsNamespace);
for (DataConfig.Entity entity : dataImporter.getConfig().document.entities) {
String key = entity.name + "." + SolrWriter.LAST_INDEX_KEY;
String lastIndex = persistedProperties.getProperty(key);
if (lastIndex != null) {
indexerNamespace.put(key, lastIndex);
} else {
indexerNamespace.put(key, DataImporter.DATE_TIME_FORMAT.get().format(EPOCH));
}
}
resolver.addNamespace(DataConfig.IMPORTER_NS_SHORT, indexerNamespace);
resolver.addNamespace(DataConfig.IMPORTER_NS, indexerNamespace);
return resolver;
} catch (Exception e) {
wrapAndThrow(SEVERE, e);
// unreachable statement
return null;
}
}
代码中的名为indexrnamespace的HashMap中的所有内容都可以在sql语句中通过{dih.key}的方式取得。比如dih.LAST_INDEX_TIME ,dih.request.said……等等。