您的位置:首页 > 数据库

solr 从数据库导入数据,全量索引和增量索引

2016-02-28 20:46 579 查看
首先说一下是从mysql数据库导入数据

这里使用的是mysql测试。

1、先在mysql中建一个表:solr_test



2、插入几条测试数据:



3、用记事本打solrconfig.xml文件,在solrhome文件夹中。E:\solrhome\mycore\conf\solrconfig.xml

(solrhome文件夹是什么,参见:/article/4826743.html)

加入这个节点:

<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>


4、新建一个data-config.xml文件,与solrconfig.xml同一个目录下。内容为



<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/test"
user="root"
password="root" />
<document>
<entity name="solr_test" transformer="DateFormatTransformer"
query="SELECT id, subject, content, last_update_time FROM solr_test WHERE id >= ${dataimporter.request.id}">
<field column='last_update_time' dateTimeFormat='yyyy-MM-dd HH:mm:ss' />
</entity>
</document>
</dataConfig>




说明:这里使用了一个${dataimporter.request.id},这个是参数,后面在做数据导入时,会使用到,以此条件为基准读数据。

5、复制解压出的solr jar包solr-dataimporthandler-4.10.0.jar和solr-dataimporthandler-extras-4.10.0.jar到tomcat solr webapp的WEB-INF\lib目录下。

当然,也包括mysql的jdbc jar包:mysql-connector-java-5.1.7-bin.jar

(还有一种方法是在solrconfig.xml中加入lib节点,然后把jar包放到solrhome下,这样可以不在WEB-INF\lib中加入jar包)

6、用记事本打开schema.xml,在在solrhome文件夹中(同第3点)。内容为:



<?xml version="1.0" ?>
<schema name="my core" version="1.1">

<fieldtype name="string"  class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="text_cn" class="solr.TextField">
<analyzer type="index" class="org.wltea.analyzer.lucene.IKAnalyzer" />
<analyzer type="query" class="org.wltea.analyzer.lucene.IKAnalyzer" />
</fieldType>

<!-- general -->
<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="subject" type="text_cn" indexed="true" stored="true" />
<field name="content" type="text_cn" indexed="true" stored="true" />
<field name="last_update_time" type="date" indexed="true" stored="true" />
<field name="_version_" type="long" indexed="true" stored="true"/>

<!-- field to use to determine and enforce document uniqueness. -->
<uniqueKey>id</uniqueKey>

<!-- field for the QueryParser to use when an explicit fieldname is absent -->
<defaultSearchField>subject</defaultSearchField>

<!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
<solrQueryParser defaultOperator="OR"/>
</schema>




7、打开solr web:



说明:

Custom Parameters填入id=1,这是在第4点中设置的参数。

Clean选项,是指是否删除未匹配到的数据。也就是在数据库select结果中没有,而solr索引库中存在,则删除。

也可以使用这个地址直接访问:

http://localhost:8899/solr/mycore/dataimport?command=full-import&clean=true&commit=true&wt=json&indent=true&entity=solr_test&verbose=false&optimize=false&debug=false&id=1


将返回结果:



配置好后,之后我们只需要使用这个url地址,就可以不段的去导入数据做索引了。(就这么简单)

8、测试查询:



当然,dataimport可以加入参数命令,让其重新加载data-config.xml

http://localhost:8899/solr/#/mycore/dataimport/command=reload-config


下面全量索引和增量索引的配置区别,注意和上面不是同一个工程(首先全量索引会把数据库中所有数据进行索引的更新,增量索引只更新数据库中增删改查过的)要使用增量索引,数据库中要有一个标识字段来表示数据的变化,我们可以使用时间戳来表示,数据更新时时间戳也更新,这样,solr通过比较时间戳的变化来增量更新索引。

1.修改multicore/new_core/conf/solrconfig.xml文件(上篇提到过的),在里面新增

Xml代码


<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">

<lst name="defaults">

<str name="config">data-config.xml</str>

</lst>

</requestHandler>

<requestHandler name="/deltaimport" class="org.apache.solr.handler.dataimport.DataImportHandler">

<lst name="defaults">

<str name="config">delta-data-config.xml</str>

</lst>

</requestHandler>

其中第一段是专门做全量索引的,第二段做增量索引(主要是靠DataImportHandler类实现)

2.新增multicore/new_core/conf/data-config.xml文件

Xml代码


<dataConfig>

<dataSource name="jdbc" driver="com.mysql.jdbc.Driver"

url="jdbc:mysql://192.168.0.81:3306/new_mall?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&useUnicode=true"

user="root" password="HyS_Db@2014"/>

<document name="mall_goods">

<entity name="MallGoods" pk="id"

query="select * from mall_goods limit ${dataimporter.request.length} offset ${dataimporter.request.offset}"

transformer="RegexTransformer">

<field column="goods_id" name="id" />

<field column="title" name="title" />

<field column="subtitle" name="subtitle" />

<field column="cover_img_path" name="coverImgPath" />

<field column="description" name="description" />

<field column="update_date" name="updateDate" />

</entity>

</document>

</dataConfig>

dataSource不用说了,数据源配置来的

entity文档中的实体配置(注意pk="id" 不能随便改 ,需要和schema.xml中的<uniqueKey>id</uniqueKey>匹配,否则会报“ org.apache.solr.common.SolrException: Document is missing mandatory uniqueKey field: id”)

query 查询语句(可分页)

transformer 暂时不清楚干啥

field定义列名

3.新增multicore/new_core/conf/delta-data-config.xml文件

Xml代码


<dataConfig>

<dataSource name="jdbc" driver="com.mysql.jdbc.Driver"

url="jdbc:mysql://192.168.0.81:3306/new_mall?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&useUnicode=true"

user="root" password="HyS_Db@2014"/>

<document name="mall_goods">

<entity name="MallGoods" pk="id"

query="select * from mall_goods"

deltaImportQuery="select * from mall_goods where goods_id='${dih.delta.id}'"

deltaQuery="select goods_id as id from mall_goods where update_date > '${dih.last_index_time}'"

transformer="RegexTransformer">

<field column="goods_id" name="id" />

<field column="title" name="title" />

<field column="subtitle" name="subtitle" />

<field column="cover_img_path" name="coverImgPath" />

<field column="description" name="description" />

<field column="update_date" name="updateDate" />

</entity>

</document>

</dataConfig>

deltaQuery查询出有更改过的id

deltaImportQuery根据id查询

4.修改multicore/new_core/conf/schema.xml文件,定义field索引配置

Xml代码


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

<field name="title" type="text_ansj" indexed="true" stored="true" required="true" multiValued="false"/>

<field name="subtitle" type="text_ansj" indexed="true" stored="true" required="false" multiValued="false"/>

<field name="coverImgPath" type="string" indexed="false" stored="true" required="true" multiValued="false" />

<field name="description" type="text_ansj" indexed="true" stored="true" required="false" multiValued="false"/>

<field name="updateDate" type="text_ansj" indexed="true" stored="true" required="false" multiValued="false"/>

注意上面选择一下text_ansj

5.solr的war包可能还缺少部分jar包,需要把mysql的jar,以及solr项目中dist目录下的jar包都放到solr的web站点中

6.开始运行

全量:http://solr.xxxx.com:8082/new_core/dataimport?command=full-import&commit=true&clean=false&offset=0&length=100000(其中0到100000的数据建立索引)

增量:http://solr.ehaoyao.com:8082/new_core/deltaimport?command=delta-import&entity=MallGoods

entity:是document下面的标签(data-config.xml)。使用这个参数可以有选择的执行一个或多个entity 。使用多个entity参数可以使得多个entity同时运行。如果不选择此参数那么所有的都会被运行。

clean:选择是否要在索引开始构建之前删除之前的索引,默认为true

commit:选择是否在索引完成之后提交。默认为true

optimize:是否在索引完成之后对索引进行优化。默认为true

debug:是否以调试模式运行,适用于交互式开发(interactive development mode)之中。

请注意,如果以调试模式运行,那么默认不会自动提交,请加参数“commit=true”

注意:在做增量索引的时候

很容易出现deltaQuery has no column to resolve to declared primary key pk='id'这种异常

主要是因为ID" must be used as it is in 'deltaQuery' select statement as "select ID from ..."

(if you different name for ID column in database, then use 'as' keyword in select statement. In my case I had 'studentID' as primary key in student table. So I used it as "select studentID as ID from ..."

--> The same applies to 'deletedPkQuery'

At present its working fine for me. Any updation in database is reflected in Solr as well.

所以,delta-data-config.xml文件需要注意一下pk的值

参考连接:
http://shiyanjun.cn/archives/444.html http://blog.duteba.com/technology/article/70.htm http://www.devnote.cn/article/89.html http://qiaqia26.iteye.com/blog/1004996 http://zzstudy.offcn.com/archives/8104 http://blog.csdn.net/duck_genuine/article/details/5426897
------------------------------------------------------------------------------------------------------------------------------

最后补充:

有时候需要删除索引数据,可以这样删除
http://xxxx/new_core/update/?stream.body=<delete><query>*:*</query></delete>&stream.contentType=text/xml;charset=utf-8&commit=true
new_core 表示你要删除哪个核下面的索引

java代码调用增量和全量索引

import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;

import base.util.ConfigUtil;

public class SolrService {
private static Logger log = Logger.getLogger(SolrService.class);

private static HttpSolrServer solrServer;

static {
solrServer = new HttpSolrServer(ConfigUtil.getValue("solr.url"));
solrServer.setConnectionTimeout(5000);
}

/**
* 增量/全量建立索引 。
*
* @param delta ture,增量建立索引;false,重建所有索引
*/
public static void buildIndex(boolean delta) {
SolrQuery query = new SolrQuery();
// 指定RequestHandler,默认使用/select
query.setRequestHandler("/dataimport");

String command = delta ? "delta-import" : "full-import";
String clean = delta ? "false" : "true";
String optimize = delta ? "false" : "true";

query.setParam("command", command)
.setParam("clean", clean)
.setParam("commit", "true")
.setParam("entity", "article")
.setParam("optimize", optimize);
try {
solrServer.query(query);
} catch (SolrServerException e) {
log.error("建立索引时遇到错误,delta:" + delta, e);
}
}

}


相关说明:

主要原理:是利用率每次我们进行import的时候在solr.home的conf下面生成的dataimport.properties文件,此文件里面有最近一次导入的相关信息,如:

我的文件位置为
/root/solr-4.5.1/example/solr/collection1/conf


我的文件内容为
#Mon Dec 09 14:06:03 CST 2013
last_index_time=2013-12-09 14\:06\:00
article.last_index_time=2013-12-09 14\:06\:00


last_index_time是最近一次增量或全量索引的时间,通过比较这个时间和我们数据库表中的update_time列即可得出哪些是之后修改或者添加的。

data-config.xml说明:

query是获取全部数据的SQL
deltaImportQuery是获取增量数据时使用的SQL
deltaQuery是获取主键的SQL

参数说明:

clean:设置建索引前是否删除之前的索引;
commit:设置建索引后是否自动提交;
entity:mysql-data-config.xml entity name中配置的名称,如果配有多个,且这里不指定,所有entity都会被执行;
optimize:设置建索引后是否自动优化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: