solr使用dataimporter.request的参数实现增量导入
一、${dih.delta.id}和${dataimporter.last_index_time}实现的solr增量导入
该增量导入方式,当数据库时间慢于solr服务器时间,会导致增量导入的数据缺少记录;会发出N+1条sql,效率低。
1、 配置
1)
需要导入的表结构
create table SOLRTEST
(
ID number,
EMP_NAME VARCHAR2(100),
CREATETIME DATE
)
2) solr配置
i) 创建索引库
${solr.home}\bin\solr.cmdcreate -c solrtest
ii) 配置${solr.home}\server\solr\solrtest\conf\managed-schema文件
配置中文分词器
<fieldType name="solr_cnAnalyzer" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
</analyzer>
</fieldType>
配置索引字段
<field name="empName" type="solr_cnAnalyzer" indexed="true" stored="true" required="true" multiValued="false" />
<field name="createtime" type="pdate" indexed="true" stored="true" required="true" multiValued="false" />
iii) 指定dataImportHandler的数据源配置文件,${solr.home}\server\solr\solrtest\conf\solrconfig.xml文件中添加:
<requestHandler name="/dataimport" class="solr.DataImportHandler">
<lst name="defaults">
<str name="config">./data-config.xml</str>
</lst>
</requestHandler>创建${solr.home}\server\solr\solrtest\conf\data-config.xml,并配置:
iv) 创建${solr.home}\server\solr\solrtest\conf\data-config.xml,并配置:
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<dataSource type="JdbcDataSource"
driver="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.1:1521:orcl"
user="scott"
password="tiger"/>
<document>
<entity pk="ID" name="solrtest"
query="select * from solrtest"
deltaImportQuery = "select * from solrtest where id='${dih.delta.ID}'"
deltaQuery="select id from solrtest where createtime > to_date('${dataimporter.last_index_time}','yyyy-mm-dd hh24:mi:ss')">
<field column="ID" name="id"/>
<field column="EMP_NAME" name="empName"/>
<field column="CREATETIME" name="createtime"/>
</entity>
</document>
</dataConfig>
配置文件中,列字段(字段名带下划线,oracle数据库)使用小写,导致出错
查看${solr.home}\server\logs日志文件,有报错:
2、数据库时间慢于solr服务器时间,导致增量导入数据不一致
solr增量导入的通常配置方式是,在数据导入配置文件“data-config.xml”中配置的sql中,引用内置变量${dataimporter.last_index_time}(最近一次索引的时间)。${dataimporter.last_index_time}变量对应的是solr服务器${solr.home}\server\solr\solrtest\conf\dataimport.properties文件中记录的时间
当数据库时间慢于solr服务器时间不匹配时,导入数据会缺失,时间差的部分。
3、 发出N+1条sql,效率慢
网页中手动执行增量同步
N+1条sql
二、使用dataimporter.request的参数实现指定范围导入
在solr导入的配置文件${solr.home}\server\solr\solrtest\conf\data-config.xml中,可以引用dataimporter.request的参数
网页中指定dataimporter.request的参数,导入
startTime=2018-06-01 00:00:00&endTime=2018-07-05 23:59:59
仅发出一条sql
select * from solrtest where createtime between to_date(‘2018-06-01 00:00:00’, ‘yyyy-mm-dd hh24:mi:ss’) and to_date(‘2018-07-05 23:59:59’, ‘yyyy-mm-dd hh24:mi:ss’)
三、java使用solrj客户端API,实现增量导入
实现思路是,首先获取solr库中记录的最近日期,再导入从最近日期到当前时间点的数据
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocumentList; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by panzp on 2018/6/25. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring-temp3.xml"}) public class solrImportTest { @Autowired private HttpSolrClient httpSolrClient; @Test public void testImport() throws Exception { importIndex(); } /** * 首先获取solr库中记录的最近日期,再导入从最近日期到当前时间点的数据 * * @throws Exception */ public void importIndex() throws Exception { SolrQuery query = new SolrQuery(); query.setRequestHandler("/dataimport"); query.setParam("command","full-import"); query.setParam("clean","false"); //获取solr库中记录的最近日期 Date retDate = retLastDate(); if(retDate != null){ //UTC时差8小时 retDate = new Date(retDate.getTime() - 8*60*60*1000); }else{ //没有记录则设置表中最早时间之前 retDate = new Date(new Date().getTime() - 1000*24*60*60*1000); } DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String sourceDate = dateFormat.format(retDate); //当前时间点 String targetDate = dateFormat.format(new Date()); query.setParam("startTime",sourceDate); query.setParam("endTime",targetDate); httpSolrClient.query(query); } //获取solr库中记录的最近日期 public Date retLastDate() throws IOException, SolrServerException { SolrQuery solrQuery = new SolrQuery("*:*"); solrQuery.addSort("createtime", SolrQuery.ORDER.desc); QueryResponse response = httpSolrClient.query(solrQuery); SolrDocumentList docs = response.getResults(); if(docs.size()>0){ return (Date) (docs.get(0).get("createtime")); } return null; } }