设为首页 收藏本站
查看: 706|回复: 0

[经验分享] Solr中DIH模式的使用

[复制链接]

尚未签到

发表于 2016-12-16 08:22:22 | 显示全部楼层 |阅读模式
  Solr中使用DIH(DataImportHandler)模式
  最早只是使用全量导入功能,即full-import
  网上能搜索到的大部分demo多采用的情况是建立索引,查询,都是在同一个容器内操作,即开启同一个tomcat/jetty等
  通过http请求中加入相应的参数即完成了相关操作,如:
  http://localhost:8080/dataimport?command=full-import

  http://localhost:8080/dataimport?command=delta-import
  http://localhost:8080/solr/select/?q=*:*&version=2.2&start=0&rows=100&indent=on&group=true&group.field=albumId&group.ngroups=true
  group用来分组,group.ngroups用来统计命中的数量,不过貌似这个东西比较慢
  或者通过代码

private static final String DEFAULT_URL = "http://localhost:8983/solr/";
@Before
public void init() {
try {
server = new CommonsHttpSolrServer(DEFAULT_URL);
httpServer = new CommonsHttpSolrServer(DEFAULT_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}

   这样做的前提就是必须先启动一个容器,非常不便于单元测试;
  如果不启动容器,则无法完成上述操作
  而在代码中如果不通过jetty等来进行操作,Solr提供了如下方式:

private void initCore(){
System.setProperty("solr.solr.home", "/home/admin/solr");
CoreContainer.Initializer init = new CoreContainer.Initializer();
try {
core =   init.initialize().getCore(CORE_NAME);
} catch (Exception e){
logger.error("error occur when create core:{}", CORE_NAME);
}
}
  
 首先建立初始化一个core,你可以设置一个全局的

SolrCore core = null;
  如果有全量的操作
  如下所示:

                if(core==null){
initCore();
}
try {
SolrRequestHandler requestHandler = core.getRequestHandler("/dataimport");
NamedList params = new NamedList();
params.add("command", DataImporter.FULL_IMPORT_CMD);
params.add("synchronous", Boolean.TRUE);
params.add("clean", Boolean.TRUE);
SolrQueryRequest req = new LocalSolrQueryRequest(core,params) ;
SolrQueryResponse rsp = new SolrQueryResponse();
requestHandler.handleRequest(req, rsp);
} catch (Exception e) {
result = Boolean.FALSE;
logger.error("error",e);
}

  这样便完成了数据的全量导入,你太幸运了,不过在这之前你必须完成以下操作
  第一:配置schema.xml,其中主要配置一下东西:
  1 <fields></fields>这个是你要建立索引所需要的所有的字段
  2 <uniqueKey>id</uniqueKey>(可选,如果你不打算在后续的db-data-config.xml)中配置pk,那么这里就是必须的,
  如果你在db-data-config.xml中配置了pk那么这个就不是必须的了
  第二:配置solrconfig.xml,这个当中要做的事情是
  添加:

<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">db-data-config.xml</str>
</lst>
</requestHandler>
   既然这里配置了
  db-data-config.xml
  那么
  第三:配置db-data-config.xml
  这个文件中主要配置了大量的field的属性

 
<dataConfig>
<dataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/test"
user="test" password="test" /><!-- 这里定义datasource(数据源)solr默认采用JdbcDataSource,这里你可以使用自己的自定义的XXXDataSource-->
<document>
<entity name="item"
query="select * from student where studentnum > 1" pk="id"
deltaImportQuery="select * from student where id='${dataimporter.delta.id}'"
deltaQuery="select id from studentwhere  gmt_modified > '${dataimporter.last_index_time}'">
<field column="id" name="id" />
<field column="username" name="username" />
<field column="studentnum" name="studentnum" />
<field column="birthday" name="birthday" />
<field column="pic" name="pic" />
<entity name="course" transformer="com.my.dump.test.transformer.CourseTransformer" pk="id"
query="select id,CONTENT from course where studentnum='${item.studentnum}'"
deltaQuery="select id,studentnum from course where  gmt_modified > '${dataimporter.last_index_time}'"
parentDeltaQuery="select id from student where studentnum='${course.studentnum}'">
<field name="prop" column="content" />
</entity>
</entity>
</document>
</dataConfig>
  dataSource可以自定义,只需要继承

public class JdbcDataSource extends
DataSource<Iterator<Map<String, Object>>> {
  例如:

<dataSource type="com.my.test.dataimport.StudentDataSource"/>
  document中使用的是自己要被加入到索引中的field
  query,被用来做为全量导入的时候使用
  deltaImportQuery 这个是在增量时使用的修改语句,其中需要注意的是dataimporter.delta这个前缀一定要带
  pk,根据我艰苦卓绝的跟踪代码知道这个pk其实作用只是用来对deltaQuery查询出来的内容放入到一个map中的时候作为key用的
  如果你不想deltaQuery查询出来的结果最后出现混乱,那么最好保证pk是唯一的
  deltaQuery,这个是用来查询需要被更新的对象的主键,一边deltaImportQuery使用
  transformer:很多时候数据库中的字段不能满足你的需要,比如存储了用户生日,那么你需要将他的生肖存储,则此时需要对生日做自己的处理
  那么你需要一个

public class PropTransformer extends Transformer {
 这样实现它的

        @Override
public Object transformRow(Map<String, Object> row, Context context) {
System.out.println("--------------------------------------");
String content = (String)row.get("CONTENT");
//转换处理逻辑
if(content==null){
return null;
}
try {
row.put(BABYNICK, kvMap.get(BABYNICK));
return row;
} catch (Exception e) {
return null;
}
}
  这样就可以使用自己的操作了
  parentDeltaQuery:这个是当子类发生变化是同时要通知主类,因为solr现在还没有能够只修改对应document中的个别属性的能力,通常是删除后重新插入
  所以在这里也是要查询出子类对应的主类的主键id
  Solr的DIH功能工作过程如下:
  1.加载配置文件,确定命令类型,加载datasource
  2.如果是full-import,则执行全量导入,依据配置文件或代码中的query配置执行
  3.如果是delta-import,首先从根entity的下一级中执行detlaQuery,查找满足的row,同时根据pk从row中取出pk的value,然后以value作为键,以row作为值存入到map中,检测是否含有parentDeltaQuery,如果存在,从上一个map中取出parentDeltaQuery需要的参数值,查处parent的pk,依次递归,知道拿到根元素的pk,最终将所有的根元素的pk放入到一个map中,依次执行deltaImportQuery,这样所有相关的数据将被更新
  其中让人头疼的是,在加载dataimport.properties文件时,通过查看文件发现只有如下配置:

#Wed Feb 08 10:56:12 CST 2012
item.last_index_time=2012-02-08 10\:56\:11
last_index_time=2012-02-08 10\:56\:11

  那么我就这样处理

deltaQuery="select id,user_id from user_profile where  gmt_modified > '${last_index_time}'"
  
结果发现执行后的sql中last_index_time是空的,经过艰苦卓绝的跟踪代码发现,原来最后生成的 resolver对象中存放的数据(map)的key没有以last_index_time开头的,只有以dataimport为key的map为value,其中value中有lasta_index_time和item.last_index_time,所以当加上dataimport前缀后预期的结果出现了,也就是说其中的一些配置并不是随意的,有些属于固定配置,

  还有就是pk的作用一直没搞懂,也是通过跟踪代码发现pk本身的作用只是保证查询出来的row放入map中的时候作为key使用的,所以么个entiy如果涉及到增量你就得有pk属性存在
  具体的操作过程详见Solr中的DocBuilder这个类
  solr搜索的时候使用类sql的group如下:

group=true&group.field=sellerId&group.format=simple

其中sellerId是索引字段

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-314898-1-1.html 上篇帖子: Solr:Performing queries and handling results 下篇帖子: solr cloud 之添加,删除,更新Document
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表