solr自带了DIH(DataImportHandler),提供了一站式的全量和增量方案,所以本着简单方便的理念,所以就是通过DIH来解决问题
http://wiki.apache.org/solr/DataImportHandler,DIH的官方文档,里面很多都已经讲的很到位,依据其中的说明,很多就配置完成了全量索引的文件,顺利完成了全量索引的方案,不久需要进行增量索引,忽然发现其中有好多配置比较蛊惑人心,所以就决定依着源码进行细致的研究
下面是对官方文档的一部分翻译,以及自己的研究的一点心得
目标:
读取属于数据库的数据
根据配置,聚合多列和多表的数据
用documents去更新solr
进行full imports,根据配置
通过最后的修改时间,侦测插入和更新,进行delta import
定时进行full imports和delta imports
读取和索引数据,从xml/(http/file)
设计概述
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">/home/username/data-config.xml</str>
</lst>
</requestHandler>
提供了full-import和delta-import
<dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/dbname" user="db_username" password="db_password"/>
使用RDBMS
使用full-import和delta-import(get new inserts/updates)
name:如果有多个datasources
<dataSource name="jdbc" driver="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@//hostname:port/SID" user="db_username" password="db_password"/>
多个数据源
<dataSource type="JdbcDataSource" name="ds-1" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://db1-host/dbname" user="db_username" password="db_password"/>
<dataSource type="JdbcDataSource" name="ds-2" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://db2-host/dbname" user="db_username" password="db_password"/>
配置JdbcDataSource
driver:
url
user
password
jndiName
batchSize:
convertType:默认为false,自动的读取数据,用目标solr data-type
autoCommit:If set to 'false' it sets setAutoCommit(false)
readOnly : If this is set to 'true' , it sets setReadOnly(true), setAutoCommit(true), setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED),setHoldability(CLOSE_CURSORS_AT_COMMIT) on the connection <!> Solr1.4
transactionIsolation : The possible values are [TRANSACTION_READ_UNCOMMITTED, TRANSACTION_READ_COMMITTED, TRANSACTION_REPEATABLE_READ,TRANSACTION_SERIALIZABLE,TRANSACTION_NONE]
配置data-config.xml
schema的配置
name:
processor:当datasource不是RDBMS时,需要,默认为SqlEntityProcessor
transformer:
dataSource:
threads:必须放置在根目录(现在已被移除,从solr 4.0)
pk:entity的主键,这是可选的,紧紧在使用delta-imports时,才需要,但是它和定义在schema.xml中的uniqueKey没有什么关系,但是它们两个可以是一致的
rootEntity:位于document下面的entities,将会作为根实体,如果它被设置为false,位于它下面的实体将会被当做根实体,对于返回的每一个根实体都将在solr中进行创建
onError:abort|skip|continue.默认为abort,skip:忽略掉当前的文档,continue:如果这个错误没有出现,将会继续
preImportDeleteQuery:在全部导入之前,这将会被清除索引
postImportDeleteQuery:在全部导入之后,这将会被用来清除索引
对于SqlEntityProcessor:
query
deltaQuery:
parentDeltaQuery:
deletePkQuery:
deltaImportQuery
commands:
full-import:全量导入
entity:under document tag,
clean: true 在索引数据之前是否先清除已有的索引,
commit:true 在索引之后是否进行提交,
optimize: 3.6之前为true,之后为false,在对数据进行索引之后,是否进行索引的优化,
debug:默认为false,使用在交互开发模式,在这种模式下面,文档永远不会被自动提交,如果你想要在进行debug模式的时候,并且也自动提交,添加commit=true,作为一个请求的参数
delta-import:clean,commit,optimize,debug
status:created, deleted,queries run, rows fetched, status
reload-config:在data-config改变时,可以不启动solr直接加载配置文件
abort:遗弃一个操作
注:clean:
Delta-Import Example
<dataConfig>
<dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />
<document name="products">
<entity name="item" pk="ID"
query="select * from item"
deltaImportQuery="select * from item where ID='${dih.delta.id}'"
deltaQuery="select id from item where last_modified > '${dih.last_index_time}'">
<entity name="feature" pk="ITEM_ID"
query="select description as features from feature where item_id='${item.ID}'">
</entity>
<entity name="item_category" pk="ITEM_ID, CATEGORY_ID"
query="select CATEGORY_ID from item_category where ITEM_ID='${item.ID}'">
<entity name="category" pk="ID"
query="select description as cat from category where id = '${item_category.CATEGORY_ID}'">
</entity>
</entity>
</entity>
</document>
</dataConfig>
<dataConfig>
<dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />
<document>
<entity name="item" pk="ID" query="select * from item"
deltaImportQuery="select * from item where ID=='${dih.delta.id}'"
deltaQuery="select id from item where last_modified > '${dih.last_index_time}'">
<entity name="feature" pk="ITEM_ID"
query="select DESCRIPTION as features from FEATURE where ITEM_ID='${item.ID}'"
deltaQuery="select ITEM_ID from FEATURE where last_modified > '${dih.last_index_time}'"
parentDeltaQuery="select ID from item where ID=${feature.ITEM_ID}"/>
<entity name="item_category" pk="ITEM_ID, CATEGORY_ID"
query="select CATEGORY_ID from item_category where ITEM_ID='${item.ID}'"
deltaQuery="select ITEM_ID, CATEGORY_ID from item_category where last_modified > '${dih.last_index_time}'"
parentDeltaQuery="select ID from item where ID=${item_category.ITEM_ID}">
<entity name="category" pk="ID"
query="select DESCRIPTION as cat from category where ID = '${item_category.CATEGORY_ID}'"
deltaQuery="select ID from category where last_modified > '${dih.last_index_time}'"
parentDeltaQuery="select ITEM_ID, CATEGORY_ID from item_category where CATEGORY_ID=${category.ID}"/>
</entity>
</entity>
</document>
</dataConfig>
query:在full-import中,获取需要的
deltaImportQuery:当跑delta-import时,deltaImportQuery将获取到的数据填充到字段中
deltaQuery:自从上一次索引时间以来,给出改变的主键
parentDeltaQuery:parentDeltaQuery使用当前表的改变的行,(通过deltaQuery来获取),给出在父表中变化的行,这个是需要的,因为无论何时,在子表中的数据的改变,我们需要重新生成有这些
字段的文档。
query查询给出的每一行,子查询都会被执行
deltaQuery查询给出的每一行,parentDeltaQuery父级查询被执行
在root/child中的任一行发生改变,我们将重新产生这个彻底的solr document
这个"deltaImportQuery"是一个solr 1.4特性,
Solr3.1
这个handler检查确定你声明的主键域,是在所有查询的结果中,在一个实例中,这个要求使用SQL别称,当从1.4更新到3.1时,
配置property writer
在dataConfig tag下面增加一个tag "propertyWriter"
<propertyWriter dateFormat="yyyy-MM-dd HH:mm:ss" type="SimplePropertiesWriter" directory="data" filename="my_dih.properties" locale="en_US" />
type:这个实现的class
filename:simplePropertiesWriter
directory:simplePropertiesWriter
dateFormat:指定了格式化时间
locale:SimplePropertiesWriter/ZKPropertiesWriter,
Interactive Development Mode交互开发模式
点击"Debug Mode"按钮,将会启用这个功能,它将展示你的当前的DIH
注意点:你需要配置需要debug文档的行数,start和rows参数,
选择"verbose"选项。获取中间步骤的详细信息。查询到的,和传给transformter的,以及输出的
如果在跑的过程中有异常出现,这个堆栈将会被正确展示
这个域将会被实体产生,如果这个字段没有在schema.xml中明确声明,transformers就不会对此做出处理。
dataimportHandler:
对于根目录(root)的entity,如果不提供PK,则可以通过dataimporter.delta.id,进行数据的获取
如果提供了PK,也不能通过
也不能通过这种方式指定ID,
但是对于child,则不能通过dataimporter.delta,来指定,必须通过entity.name.Id,来指定,且增量导入的时候,pk必须有,且,pk的值的定义必须和deltaQuery,中的一致
parentDeltaQuery 这个在子节点中是查询的父节点中deltaImportQuery中需要的条件,通过parentDeltaQuery 查询出来的条件,将会和父节点中的deltaQuery组合起来,变成一起的条件,供父节点的deltaImportQuery中的条件去查询
deltaImportQuery 这个只是在根节点起作用
未完待续。。。。。