才疏学浅,欢迎批评指正
Solr7.5利用DIH导入结构化数据构建索引
7.5利用DIH导入结构化数据构建索引
1.什么是DIH
按照solr7.5官方文档给出的说法:
The Data Import Handler (DIH) provides a mechanism for importing content from a data store and indexing it.
数据导入处理程序(DIH)提供了一种从数据存储中导入内容并对其进行索引的机制。
其中,
DataSource:指需要导入数据的数据源的位置
Entity:
对于solr而言:entity指一个包含多个字段的文档,solr对文档中的字段进行索引
对于关系型数据库而言:entity指数据库中的一张表,数据库表中的一行(rows)对应solr中的一个文档(documents),表中的一个字段(columns ),对应solr中的一个字段(fields)
2.使用DIH
1.引入数据库驱动
在solr\server\solr-webapp\webapp\WEB-INF\lib下,放入需要的jar,这里是mysql
2.打开solrconfig.xml,添加如下内容:
1)引入DIH的jar包
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-dataimporthandler-\d.*\.jar" />
也就是dist文件夹中以solr-dataimporthandler开头的相关jar包
2)指定DIH配置文件
<requestHandler name="/dataimport"
class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">solr-data-config.xml</str>
</lst>
</requestHandler>
其中solr-data-config为DIH配置文件的文件名。
3.在conf文件夹下创建DIH的配置文件(这里为solr-data-config.xml)
4.配置DIH
在刚刚新建的solr-data-config.xml中添加如下内容
<dataConfig>
<dataSource name="db_fileManagement" type="JdbcDataSource" driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/db_fileManagement" user="root" password="123456"/>
<document>
<entity name="tb_test1" PK="DocumentNo" dataSource="db_fileManagement"
query="select * from tb_test1 where IS_DEL = '0'"
deltaQuery="select DocumentNo from tb_test1 where LAST_MODIFIED > '${dataimporter.tb_test1.last_index_time}'"
deltaImportQuery="select * from tb_test1 where DocumentNo = '${dih.delta.DocumentNo}'"
deletedPkQuery="select DocumentNo from tb_test1 where IS_DEL = '1'">
<field column="DocumentNo" name="document_number"/>
<field column="PartNo" name="partno_s"/>
<field column="No" name="no_s_c"/>
<field column="PersonLiable" name="personliable_s_c"/>
<field column="Title" name="title_ik_c"/>
<field column="TABLE_ID" name="table_id_s"/>
</entity>
</document>
</dataConfig>
其中:
dataSource中为数据源的相关配置:
属性名 | 作用 |
---|---|
name | 数据库名称 |
type | 数据源类型 |
driver | 数据库驱动名称 |
url | 数据库地址 |
user | 用户密码 |
password | 用户密码 |
其中数据源类型还可以有FieldReaderDataSource等其他类型
entity配置相关SQL语句
属性名 | 作用 |
---|---|
name | 表的名称 |
PK | 表的主键名称 |
dataSource | 表所属的数据源的名称 |
query | 查询全量导入数据 |
deltaQuery | 查询增量导入数据的主键L,为deltaImportQuery作准备 |
deltaImportQuery | 根据从deltaQuery得到的主键,查询定义增量导入数据全部字段 |
deletedPkQuery | 查询需要删除数据的主键,删除这些记录 |
field配置数据库表中的记录与solr中document之间的关系
属性名 | 作用 |
---|---|
column | 字段在数据库表中的名称 |
name | 字段在solr中field的名称 |
4.导入数据
各参数的含义如下
参数名称 | 取值 | 意义 |
---|---|---|
command | full-import/delta-import/status/reload-config/abort | 全量导入/增量导入/导入的状态/重新载入配置文件/终止导入 |
verbose | true/false | 是否输出详细的步骤 |
clean | true/false | 是否删除原有的全部索引 |
commit | true/false | 导入后是否提交 |
optimize | true/false | 是否优化索引,优化索引会提高检索效率,但会增加导入的时间 |
debug | true/false | 是否进入debug模式,该模式下数据不会提交 |
entity | 与solr-data-config中配置的entity名称一致 | 所要导入的表的名称 |
使用solrj实现导入数据操作
全量导入
SolrQuery solrQuery = new SolrQuery();
solrQuery.setRequestHandler("/dataimport");//指定RequestHandler,默认为select
solrQuery.setParam("command","full-import");//指定导入方式
solrQuery.setParam("clean","false");//是否删除core中的索引,默认为true !!!
solrQuery.setParam("optimize","false");//操作结束后是否对索引进行优化
solrQuery.setParam("entity",tableName);//指定需要导入的table
solrQuery.setParam("commit","true");//是否提交
QueryResponse queryResponse = solrClient.query(solrQuery);
while(true){
if(this.getImportInfo(solrClient)) {break;}
Thread.sleep(1000);
}
增量导入
SolrQuery solrQuery = new SolrQuery();
solrQuery.setRequestHandler("/dataimport");//指定RequestHandler,默认为select
solrQuery.setParam("command","delta-import");//指定导入方式
solrQuery.setParam("clean","false");//是否删除core中的索引,默认为true !!!
solrQuery.setParam("optimize","false");//操作结束后是否对索引进行优化
solrQuery.setParam("entity",tableName);//指定需要导入的table
solrQuery.setParam("commit","true");//是否提交
QueryResponse queryResponse = solrClient.query(solrQuery);
while(true){
if(this.getImportInfo(solrClient)) {break;}
Thread.sleep(1000);
}
在全量或增量导入时,solr往往会需要一定时间,而此时虽然也返回queryResponse,但需要对其中的status进行判断,idle为导入成功的标志,busy则此时仍在导入
//getImportInfo方法
SolrQuery solrQuery = new SolrQuery();
solrQuery.setRequestHandler("/dataimport");//指定RequestHandler,默认为select
solrQuery.setParam("command","dataimport");
QueryResponse queryResponse = solrClient.query(solrQuery);
if(!"busy".equals(queryResponse.getResponse().asShallowMap().get("status")))
return true;
else
return false;
3.使用DIH中遇到的一些问题
1.时区问题:
solr默认的是UTC时区,造成数据库中记录的时间与solr中索引构建的时间不一致,应修改UTC为东八区时间。
在bin下找到solr.cmd
修改
IF "%SOLR_TIMEZONE%"=="" set SOLR_TIMEZONE='UTC'
为
IF "%SOLR_TIMEZONE%"=="" set SOLR_TIMEZONE='UTC+8'
2.如何根据数据库中数据的变化自动增量构建索引:
-
在数据库表中新增timestamp类型的字段,该字段会保存对应记录的更新的最新时间。这里的字段名称为LAST_MODIFIED。
-
solr在导入数据时,在conf下的dataimport.properties文件下,会记录下每个entity的最新导入时间。
tb_test3.last_index_time=2019-05-13 16\:37\:33
tb_test2.last_index_time=2019-05-13 16\:42\:31
last_index_time=2019-05-15 21\:39\:03
tb_test1.last_index_time=2019-05-15 21\:39\:03
- 根据dataimport.properties文件中的last_index_time和数据库中记录变化的时间LAST_MODIFIED,选择需要增量导入的数据。因此定义deltaQuery为:
select DocumentNo from tb_test1 where LAST_MODIFIED > '${dataimporter.tb_test1.last_index_time}'
dataimporter.tb_test1.last_index_time,其中tb_test1为对应的表名
3.如何根据数据库中记录的删除,实现solr中索引的删除。
- 在数据库表中新增字段isDel,用以标识当前记录是否需要删除。当记录对应的索引需要删除时,将该字段置为1。(即实现数据的软删除)
- 调用接口,增量更新索引。获得需要被删除的记录的主键,删除索引
select DocumentNo from tb_test1 where IS_DEL = '1'
- 删除索引后,再删除数据库中字段为1的记录,即硬删除。从而实现数据库数据与索引数据的一致。
4.虽然solr可以实现不同数据源中导入不同数据库表中的数据,但这些表的表名必须各不相同,即使是在不同数据源下,也不能有相同的表名。
5.导入数据时,可能会遇到不同表中有相同名称主键的问题,会造成主键的冲突。可以增加UUID,自动生成UUID,将UUID对应的field作为document的主键
- 在managed-schema文件中增加如下配置
<fieldType name="uuid" class="solr.UUIDField" indexed="true" docValues="true"/>
修改原id的field为
<field name="id" type="uuid" indexed="true" stored="true" required="true" multiValued="false" />
修改原_root_的field为
<field name="_root_" type="uuid" indexed="true" stored="false" docValues="false" />
同时id作为uniqueKey不变
<uniqueKey>id</uniqueKey>
这样solr可以以UUID作为主键
- 在solrconfig.xml中增加
<!-- 生成UUID -->
<updateRequestProcessorChain name="uuid">
<processor class="solr.UUIDUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.LogUpdateProcessorFactory" />
<processor class="solr.DistributedUpdateProcessorFactory" />
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
修改
<initParams path="/update/**,/query,/select,/tvrh,/elevate,/spell,/browse,update">
<lst name="defaults">
<str name="df">text</str>
<str name="update.chain">uuid</str>
</lst>
</initParams>
<requestHandler name="/update/extract"
class="solr.extraction.ExtractingRequestHandler" >
<lst name="defaults">
<str name="uprefix">ignored_</str>
<str name="update.chain">uuid</str>
</lst>
</requestHandler>
<requestHandler name="/dataimport"
class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">solr-data-config.xml</str>
<str name="update.chain">uuid</str>
</lst>
</requestHandler>
这样可以solr可以自动生成UUID
6.富文本(word/pdf/txt/html)
DIH除了可以导入结构化数据外,还可以利用tika导入富文本,可见
http://lucene.apache.org/solr/guide/7_5/uploading-data-with-solr-cell-using-apache-tika.html
http://lucene.apache.org/solr/guide/7_5/uploading-structured-data-store-data-with-the-data-import-handler.html
其中的The TikaEntityProcessor和The FileListEntityProcessor部分
7.DIH配置文件中的PK可以与solr中的uniqueKey不同
今天的文章solr如何建立索引的_solr查询分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/83326.html