Solr的data-config.xml导入数据库记录

当我们要从数据库中导入数据到solr的索引库中,就需要自己配置data-config.xml文件来引入记录

dataconfig.xml的创建

  1. 首先在solrhome的core的conf文件夹加新建data-config.xml,并添加如下类似内容:
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
    <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/dp" user="root" password="123456" />
    <document>
        <entity name="haLock" query="select * from ha_lock" deltaQuery="select * from ha_lock">
            <field column="id" name="id" />
	        <field column="type" name="type" />
	        <field column="lock_kind" name="lock_kind" />
            <field column="name" name="name" />
            <field column="lock_no" name="lock_no" />
        </entity>
    </document>
</dataConfig>

2.在managed-schema中配置相应的域,field:

<field name="type" type="string" indexed="true" stored="true"/>
<field name="lock_kind" type="string" indexed="true" stored="true"/> 
<field name="lock_no" type="string" indexed="true" stored="true"/>

3.在solrconfig.xml文件中,查询到requestHandler标签的位置,并在它前面添加代码:

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

4.将solr-7.5.0\dist下的solr-dataimporthandler-7.2.1.jar和mysql驱动包mysql-connector-java-5.1.35.jar,放入…\tomcat\webapps\solr\WEB-INF\lib文件夹下;

这样一个引入数据库文档的data-config.xml基本上就建立好了

然后是关于data-config.xml文件中的一些详细配置,在标签内

  • query是获取全部数据的SQL
  • deltaImportQuery是获取增量数据时使用的SQL
  • deltaQuery是获取pk的SQL
  • parentDeltaQuery是获取父Entity的pk的SQL

Full Import(全导入)工作原理:

  • 执行本Entity的Query,获取所有数据;
  • 针对每个行数据Row,获取pk,组装子Entity的Query;
  • 执行子Entity的Query,获取子Entity的数据。

Delta Import(增量导入)工作原理:

  • 查找子Entity,直到没有为止;
  • 执行Entity的deltaQuery,获取变化数据的pk;
  • 合并子Entity parentDeltaQuery得到的pk;
  • 针对每一个pk Row,组装父Entity的parentDeltaQuery;
  • 执行parentDeltaQuery,获取父Entity的pk;
  • 执行deltaImportQuery,获取自身的数据;
  • 如果没有deltaImportQuery,就组装Query

限制:

  • 子Entity的query必须引用父Entity的pk
  • 子Entity的parentDeltaQuery必须引用自己的pk
  • 子Entity的parentDeltaQuery必须返回父Entity的pk
  • deltaImportQuery引用的必须是自己的pk

DataImportHandler

大多数的应用程序将数据存储在关系数据库、xml文件中。对这样的数据进行搜索是很常见的应用。所谓的DataImportHandler提供一种可配置的方式向solr导入数据,可以一次全部导入,也可以增量导入。

目标

 能够读取关系数据库中的数据。
 通过可配置的方式,能够将数据库中多列、多表的数据生成solr文档  
 能够通过solr文档更新solr
 提供 通过配置文件就能够导入所有数据的能力
 能够发现并处理由insert、update带来的变化(我们假定在表中有一个叫做“last-modified的列”)
 能够配置 “完全导入”和“增量导入”的时间
 让读取xml文件,并建立索引成为可配置。
 能够将其他的数据源(例如:ftp,scp,etc)或者其他格式的文档(Json,csv)以插件的形式集成到项目中。

配置dataconfig.xml:

solr document是schema,它的域上的值可能来自于多个表.

    data-config.xml的根元素是document。一个document元素代表了一种文档。一个document元素中包含了一个或者多个root实体。一个root实体包含着一些子实体,这些子实体能够包含其他的实体。实体就是,关系数据库上的表或者视图。每个实体都能够包含多个域,每个域对应着数据库返回结果中的一列。域的名字跟列的名字默认是一样的。如果一个列的名字跟solr field的名字不一样,那么属性name就应该要给出。其他的需要的属性在solrschema.xml文件中配置。


为了能够从数据库中取得想要的数据,我们的设计支持标准sql规范。这使得用户能够使用他任何想要的sql语句。root实体是一个中心表,使用它的列可以把表连接在一起。

dataconfig的结构

以下是entity的默认属性

  • name(必需的):name是唯一的,用以标识entity
  • processor:只有当datasource不是RDBMS时才是必需的。默认值是SqlEntityProcessor
  • transformer:转换器将会被应用到这个entity上,详情请浏览transformer部分。
  • pk:entity的主键,它是可选的,但使用“增量导入”的时候是必需。它跟schema.xml中定义的uniqueKey没有必然的联系,但它们可以相同。
  • rootEntity:默认情况下,document元素下就是根实体了,如果没有根实体的话,直接在实体下面的实体将会被看做跟实体。对于根实体对应的数据库中返回的数据的每一行,solr都将生成一个document。

以下是SqlEntityProcessor的属性

  • query (required) :sql语句

  • deltaQuery : 只在“增量导入”中使用

  • parentDeltaQuery : 只在“增量导入”中使用

  • deletedPkQuery : 只在“增量导入”中使用

  • deltaImportQuery : (只在“增量导入”中使用) . 如果这个存在,那么它将会在“增量导入”中导入phase时代替query产生作用。这里有一个命名空间的用法${dataimporter.delta.}

Commands

The handler 通过httprequest 向外界提供它的API . 以下是一些或许你会用到的操作

(1). full-import : "完全导入"这个操作可以通过访问URL http://:/solr/dataimport?command=full-import 完成。

  • 这个操作,将会新起一个线程。response中的attribute属性将会显示busy。

  • 这个操作执行的时间取决于数据集的大小。

  • 当这个操作运行完了以后,它将在conf/dataimport.properties这个文件中记录下这个操作的开始时间

  • 当“增量导入”被执行时,stored timestamp这个时间戳将会被用到

  • solr的查询在“完全导入”时,不是阻塞的它还有下面一些参数:

    1. clean : (default ‘true’). 决定在建立索引之前,删除以前的索引。

    2. commit: (default ‘true’). 决定这个操作之后是否要commit

    3. optimize: (default ‘true’). 决定这个操作之后是否要优化。

    4. debug : (default false). 工作在debug模式下。详情请看 the interactive development mode (see here)

(2). delta-import : 当遇到一些增量的输入,或者发生一些变化时使用 http://:/solr/dataimport?command=delta-import . 它同样支持 clean, commit, optimize and debug 这几个参数.

(3). status : 想要知道命令执行的状态 , 访问 URL http://:/solr/dataimport .它给出了关于文档创建、删除,查询、结果获取等等的详细状况。

(4). reload-config : 如果data-config.xml已经改变,你不希望重启solr,而要重新加载配置时,运行一下的命令http://:/solr/dataimport?command=reload-config

(5). abort : 你可以通过访问 url http://:/solr/dataimport?command=abort 来终止一个在运行的操作

看一个full import的例子
<document name="products">

        <entity name="item" query="select * from item">

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

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

            <field column="MANU" name="manu" />

            <field column="WEIGHT" name="weight" />

            <field column="PRICE" name="price" />

            <field column="POPULARITY" name="popularity" />

            <field column="INSTOCK" name="inStock" />

            <field column="INCLUDES" name="includes" />



            <entity name="feature" query="select description from feature where item_id='${item.ID}'">

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

            </entity>

            <entity name="item_category" query="select CATEGORY_ID from item_category where item_id='${item.ID}'">

                <entity name="category" query="select description from category where id = '${item_category.CATEGORY_ID}'">

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

                </entity>

            </entity>

        </entity>

    </document>

这里, 根实体是一个名叫“item”的表,它的主键是ID。我们使用语句 "select * from item"读取数据. 每一项都拥有多个特性。看下面feature实体的查询语句

<entity name="feature" query="select description from feature where item_id='${item.id}'">

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

   </entity> 

feature表中的外键item_id跟item中的主键连在一起从数据库中取得该row的数据。相同地,我们将item和category连表(它们是多对多的关系)。注意,我们是怎样使用中间表和标准sql连表的:

<entity name="item_category" query="select category_id from item_category where item_id='${item.id}'">
         <entity name="category" query="select description from category where id = '${item_category.category_id}'">
               <field column="description" name="cat" />
        </entity>
</entity>

短一点的 data-config

在上面的例子中,这里有好几个从域到solr域之间的映射。如果域的名字和solr中域的名字是一样的话,完全避免使用在实体中配置域也是可以的。当然,如果你需要使用转换器的话,你还是需要加上域实体的。

下面是一个更短的版本:

    <document>

        <entity name="item" query="select * from item">                    

            <entity name="feature" query="select description as features from feature where item_id='${item.ID}'"/>            

            <entity name="item_category" query="select CATEGORY_ID from item_category where item_id='${item.ID}'">

                <entity name="category" query="select description as cat from category where id = '${item_category.CATEGORY_ID}'"/>                        

            </entity>

        </entity>

    </document>

简洁了很多

增量导入命令

你可以通过访问URL DataImport http://localhost:8983/solr/dataimport?command=delta-import 来使用增量导入。操作将会新起一个线程,response中的属性statue也将显示busy now。操作执行的时间取决于你的数据集的大小。在任何时候,你都可以通过访问 http://localhost:8983/solr/dataimport 来查看状态。

当 增量导入被执行的时候,它读取存储在conf/dataimport.properties中的“start time”。它使用这个时间戳来执行增量查询,完成之后,会更新这个放在conf/dataimport.properties中的时间戳。

Delta Import(增量导入)例子:

我们将使用跟“完全导入”中相同的数据库。注意,数据库已经被更新了,每个表都包含有一个额外timestamp类型的列 叫做last_modified。我们使用这个时间戳的域来区别出哪一行是上次索引以来有更新的。

看看下面的这个 data-config.xml:

  <document name="products">

            <entity name="item" pk="ID" query="select * from item"

                deltaQuery="select id from item where last_modified > '${dataimporter.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>

注意到item实体的 属性deltaquery了吗,它包含了一个能够查出最近更新的sql语句。注意,变量{dataimporter.last_index_time} 是DataImporthandler传过来的变量,我们叫它时间戳,它指出“完全导入”或者“部分导入”的最后运行时间。你可以在data-config.xml文件中的sql的任何地方使用这个变量,它将在processing这个过程中被赋值。

注意上面例子中deltaQuery 只能够发现item中的更新,而不能发现其他表的。你可以像下面那样在一个sql语句中指定所有的表的更新。这里要特别说明一下的就是,它的细节对于一个使用者来说是一个不错的练习。

deltaQuery="select id from item where id in

                                (select item_id as id from feature where last_modified > '${dataimporter.last_index_time}')

                                or id in 

                                (select item_id as id from item_category where item_id in 

                                    (select id as item_id from category where last_modified > '${dataimporter.last_index_time}')

                                or last_modified > '${dataimporter.last_index_time}')

                                or last_modified > '${dataimporter.last_index_time}'"

但是写一个类似上面的庞大的deltaQuery 并不是一件很享受的工作,我们还是选择其他的方法来达到这个目的

<dataConfig>

    <dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />

    <document>

            <entity name="item" pk="ID" query="select * from item"

                deltaQuery="select id from item where last_modified > '${dataimporter.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 > '${dataimporter.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 > '${dataimporter.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 > '${dataimporter.last_index_time}'"

                        parentDeltaQuery="select ITEM_ID, CATEGORY_ID from item_category where CATEGORY_ID=${category.ID}"/>

            </entity>

        </entity>

    </document>

</dataConfig>

除了根实体以外,这里一共有三个查询,每个实体一个查询语句,为我们取得需要建立索引的数据。

deltaQuery: 取得上次索引更新时间以来有更新的实体的主键。

parentDeltaQuery: deltaQuery中取得当前表中更新的行,并把这些行提交给父表。因为,当子表中的一行发生改变时,我们需要更新它的父表的solr文档。

下面是一些值得注意的地方:

  • query语句返回的每一行,子实体的query都将被执行一次

  • deltaQuery返回的每一行,parentDeltaQuery都将被执行。

  • 根实体或者子实体中的行发生改变,我们将重新生成包含该行的solr文档。

关于两种数据导入就是这样,更具体内容:https://blog.csdn.net/boolbo/article/details/50352331#commentBox

猜你喜欢

转载自blog.csdn.net/qq_41674409/article/details/85143606