如有转载,请注明出处,谢谢合作!
solr中的data-config.xml这个配置文件大家都知道,但是我对其中query,deltaQuery,parentDeltaQuery,deletedPkQuery的执行过程有点迷惑,所以自己探索学习了一下,我先说自己得出来的结论(其中关于deletedPkQuery是怎么执行的任然不解),然后说明得出结论的方法。
对于data-config.xml这个配置文件,我举个简单的例子:
<dataConfig>
<dataSource>
........(这里是配置数据源的)
</dataSource>
<document>
<entity name="member" pk="id" query="select id, ...... from Member where isDeleted=false"
deletedPkQuery="select id , ...... from Member where isDeleted=true"
deltaQuery="selected id from Member where lastModifyTime>'${dataimporter.last_index_time}' ">
<entity name="connection" pk="...." query="......."
deltaQuery="......."
parentDeltaQuery="........">
<\entity>
<entity name="groupMember" pk="...." query="......."
deltaQuery="......."
parentDeltaQuery="........">
<\entity>
<\entity>
</document>
</dataConfig>
(配置文件中的isDeleted是我表中的一个字段,是用来标记删除的,true表示该条数据被删除,false表示没有被删除)
上面的配置文件只是列出了大致的结构。
我通常都是用2种http请求:一种就是fullImport,还有一种就是deltaImport。
如果是fullImport,那么就执行上面配置文件中的query语句(其他的语句不执行),并且主实体和子实体是嵌套的关系,即主实体query得到的每一行数据都将要被子实体拿去执行。
如果是deltaImport,那么执行顺序是这样的:
(简单起见,首先假设现在没有要更新的数据)首先从子实体的detaQuery开始,如上面配置文件的connection实体,先执行该实体的detaQuery,发现没有数据要更新(那么就不会执行parentDeltaQuery),然后在继续执行下一个实体groupMember里面的deltaQuery,发现也没有要更新的数据。最后执行deletedPkQuery。
首先到此为止,我觉得,当我向solr服务请求deltaImport命令的时候,它就会先执行子实体的deltaQuery(我测试的例子里面只有2层,但我相信,如果还有更多层,那么它还是会先执行子实体的deltaQuery)
你有可能会问:当我请求deltaImport命令的时候,难道只有deltaQuery和deletedPkQuery被执行吗?那parentDeltaQuery和query就不执行了吗?
我之前说了,那是在没有数据要更新的时候,它是这样一种执行顺序(当然,如果有数据要更新,它还是这种执行顺序,但情况会不一样)。
当任何一个表里面的数据有更新时。我请求delteImport命令时,它任然按照上面讨论的那种顺序执行,比如说,我在执行connection实体里面的deltaQuery时,发现了一条数据被更新了,那么这时,parentDeltaQuery就会根据这条数据的id查出它的父实体的id,我的理解是,子实体会将这变化了的数据的id告知他的父实体(请注意:deltaQuery和parentDeltaQuery也是一种嵌套关系,即deltaQuery执行的到的每一条数据都将被parentDeltaQuery执行,这在solr wiki里面有介绍)。当执行完了parentDeltaQuery后,他将继续执行下一个实体connection里面的deltaQuery,假如发现了有数据更新了,那么也一样要执行parentDeltaQuery。
综上所述,当有deltaImport请求的时候,他都是先执行deltaQuery,如果在该实体中没有发现要更新的数据,那就不执行parentDeltaQuery,直接执行下一个实体里面的deltaQuery了,如果发现了更新了数据,那么就执行parentDeltaQurery,然后继续下一个实体....
你可能会问:“照你这么说,当所有的子实体执行完了,各个实体里面的parentDeltaQuery找到的数据都到哪里去了?你不是说他会提交给相应实体的父实体吗?那这么提交的呢?”
对于第一个问题,“找到的数据到哪里去了?”,我不太确定,因为我没有看过这部分的源代码,但在测试的过程中给我的感觉是这样子的:可能会有这样的一个堆栈,把每一个实体找到的更新了的数据都压到这个堆栈里面,等所有的子实体都执行完了之后,然后执行主实体中的deletedPkQuery(为什么这时会执行这句?这是我在上面讨论过的,就是这样。先不要问我这句是怎么执行的!),然后在最后执行主实体的Query,这时主实体的query就依次取出堆栈里面的id,每次取到一个id,就嵌套执行所有子实体的query。这时就和你请求fullImport命令的时候的情况差不多了。
对于第二个问题:“你不是说他会提交给相应实体的父实体吗?那这么提交的呢?”
我想说的是,当我所谓的“堆栈”里面充满了更新了的数据的id的时候,这时就轮到主实体的query来这里取数据了,这时我发现,我的主实体里面的query的select语句被瞧瞧的改变了,比如上面data-config.xml里面主实体是member,他的query="select id, ...... from Member where isDeleted=false"在你看不见的地方改成了query="select id, ...... from Member where isDeleted=false and id=13" 而这里面的id为13的那条数据正是更新了的数据的id。所以我觉得,父实体里面的query就是通过把“堆栈”里面的id取出来,然后把“我写的query语句”拼接上这个id,然后向下一级一级执行query语句的。
假如你够细心,你一定还会问我:“那主实体里面的deletedPkQuery是不是也是和他的Query一样,被拼接上了一个id,然后将之从索引里面删除?”
唉~~问题就出在这里啊,我在测试的时候,预期也是以为被拼接上了一个id,可是结果没有,我就郁闷了,当子实体数据有更新的时候,他是怎么拿到这些数据的id然后将他的索引删除的呢?我也不知道,在网上找了一些资料,发现讲的最详细的就是这位大哥的博客了:http://blog.sina.com.cn/s/blog_539d361e0100nca5.html
可我还是不太明白,请知道的大哥解释一下!!!!
最后说明一下我是怎样得出这个结论的?
我的方法就是让这个data-import.xml出错,最简单的我将上面的配置文件做如下修改:
<document>
<entity name="member" pk="id" query="select id, ...... from Member where isDeleted=false1111"
deletedPkQuery="select id , ...... from Member where isDeleted=true2222"
deltaQuery="selected id from Member where lastModifyTime>'${dataimporter.last_index_time}' 3333">
<entity name="connection" pk="...." query=".......4444"
deltaQuery=".......5555"
parentDeltaQuery="........6666">
<\entity>
<entity name="groupMember" pk="...." query=".......7777"
deltaQuery=".......8888"
parentDeltaQuery="........9999">
<\entity>
<\entity>
</document>
我就是在每一条语句后面编号,这明显是有错的,当我进行deltaImport命令请求时,在命令提示符里面就会出现相关的错误报告,你去找第一个错误,他会说:“deltaQuery=".......5555”无法执行,那么你就知道他先执行的哪句?然后你在去掉”5555”,重启solr服务,继续请求deltaImport命令,然后又会出现别的错误,就这样,你就知道他的执行顺序了,我不知道我这样的方法合理不合理,如果已经有大哥明确了他的原理请指教!!谢谢。