Solr基础(中)-通过文件建立索引
2019-02-14 本文已影响0人
Vekaco
4.使用Tika索引Word/Excel/PDF
I.索引PDF文件
单个文件建立索引
-
导入Tika相关jar包,包括其第三方依赖POI和PDF-BOX,这些依赖包都可以在/solr-5.3.1/contrib/extraction/lib中找到。
依赖包 - 依赖包的配置方法
- 在solrconfig.xml中配置外部导入jar包的路径,导入conf/lib下所有jar文件。
<lib dir="./lib" regex=".*\.jar"/>
- 也可以直接将这些依赖包拷贝到Tomcat webapps下solr\WEB-INF\lib目录下。
两种配置方法的区别?
- jar包的加载时机不同:放在tomcat路径下配置方法,这些jar包在Tomcat启动时就立即加载;而放在core的lib目录下,是在solr初始化完成该core后根据solrconfig.xml里的<lib>元素配置的规则去皆在jar。
- 从系统维护角度:统一放在Tomcat下会显得杂乱无章,难以管理,当需要增删jar包时,很难弄清楚影响到哪些core;而放在core的lib目录下可以根据每个core的需求分开管理更方便维护。
建议:对于每个core都共有的jar放到Tomcat下管理,而对于每个core单独依赖的jar可以放置到当前core的lib目录下。*
注意:不要在Tomcat和core的lib同时加载两份相同的jar,否则可能导致引用冲突而出现java.lang.NoClassDefFoundError错误。
- 在当前core的solrconfig.xml中配置dataimport处理器并制定data-config.xml文件路径;
<requestHandler name="/dataimport" class="solr.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
- 在core的solrconfig.xml同级目录下创建data-config.xml配置文件,其内容如下。
<dataConfig>
<dataSource name="fileDataSource" type="BinFileDataSource"/>
<document>
<entity name="tika-test" processor="TikaEntityProcessor" url="C:/docs/solr-word.pdf" format="text">
<field column="Author" name="author" meta="true"/>
<field column="title" name="title" meta="true"/>
</entity>
</document>
</dataConfig>
- dataSource:表示数据源,即你要索引的文件需要转换成什么对象类型;
- BinFileDataSource:会读取文件,最后返回InputStream输出流,然后把InputStream交给EntityProcessor处理;
- EntityProcessor:主要负责将数据源转换成Document;
TikaEntityProcessor:之所以processor可以直接写别名而不需要输入类的完整包路径,是因为Solr的自定义类加载器会自动去org.apache.solr.handler.dataimport包下扫描。
- format:表示从文件中读出来的文本需要以什么格式返回,可选值有html、xml、text;
- field:将solr域与Tika提取的源数据进行映射;
- Tika内部会对付文本文件解析并提取Author、Title、Language、Publishers等源数据项,而这些数据项的名称是在Metadata.java类中定义的,该类包含在tika-core-version.jar中。可以到tika官网下载源码,到tika-core模块按照包路径org.apache.tika.metadata找到Metadata.java
/** @deprecated use TikaCoreProperties#FORMAT */ public static final String FORMAT = "format"; /** @deprecated use TikaCoreProperties#IDENTIFIER */ public static final String IDENTIFIER = "identifier"; /** @deprecated use TikaCoreProperties#MODIFIED */ public static final String MODIFIED = "modified"; /** @deprecated use TikaCoreProperties#CONTRIBUTOR */ public static final String CONTRIBUTOR = "contributor"; /** @deprecated use TikaCoreProperties#COVERAGE */ public static final String COVERAGE = "coverage"; /** @deprecated use TikaCoreProperties#CREATOR */ public static final String CREATOR = "creator"; /** @deprecated use TikaCoreProperties#CREATED */ public static final Property DATE = Property.internalDate("date"); /** @deprecated use TikaCoreProperties#DESCRIPTION */ public static final String DESCRIPTION = "description"; /** @deprecated use TikaCoreProperties#LANGUAGE */ public static final String LANGUAGE = "language"; /** @deprecated use TikaCoreProperties#PUBLISHER */ public static final String PUBLISHER = "publisher"; /** @deprecated use TikaCoreProperties#RELATION */ public static final String RELATION = "relation"; /** @deprecated use TikaCoreProperties#RIGHTS */ public static final String RIGHTS = "rights"; /** @deprecated use TikaCoreProperties#SOURCE */ public static final String SOURCE = "source"; /** @deprecated use TikaCoreProperties#KEYWORDS */ public static final String SUBJECT = "subject"; /** @deprecated use TikaCoreProperties#TITLE */ public static final String TITLE = "title"; /** @deprecated use TikaCoreProperties#TYPE */ public static final String TYPE = "type";
- 在schema.xml中定义对应的域;
<field name="text" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="title" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="author" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
- 我们在C:\docs目录下添加一个solr-word.pdf文件后,登录solr web控制台,选择dataimport,选择实例为之前创建的tika-test,点击执行成功将pdf文件建立索引。
为pdf建立索引
7.查询pdf索引结果
pdf索引结果
多个文件建立索引
通过FileListEntityProcessor来实现,用来批量处理指定文件夹下的文件。可以按照如下方式配置data-config.xml,其他配置不变。
<dataConfig>
<dataSource name="fileDataSource" type="FileDataSource"/>
<dataSource name="binFileDataSource" type="BinFileDataSource"/>
<document>
<entity name="pdfs" dataSource="fileDataSource" rootEntity="false" processor="FileListEntityProcessor" baseDir="c:/docs" fileName=".*\.pdf" recursive="true">
<field column="fileAbsolutePath" name="filePath"/>
<field column="fileSize" name ="size"/>
<field column="fileLastModified" name="lastModified"/>
<entity name="tika-multifiles-test" processor="TikaEntityProcessor" url="${pdfs.fileAbsolutePath}" format="text" dataSource="binFileDataSource">
<field column="Author" name="author" meta="true"/>
<field column="title" name="title" meta="true"/>
<field column="text" name="text"/>
</entity>
</entity>
</document>
</dataConfig>
解释:为什么要定义两个DataSource,以及两者的区别?
- FileDataSource用于将文件或者文件夹转换成Java的Reader对象,FileListEntityProcessor处理器需要接受此对象进行后续解析处理;
- BinFileDataSource用于将pdf/word/excel数据转化成Java的InputStream流对象,TikaEntityProcessor处理器接受此对象提取pdf元数据和文本数据。
II.索引Office Word文件
主要的配置还是在与data-config.xml当中,参考如下配置。
<dataConfig>
<dataSource name="fileDataSource" type="FileDataSource"/>
<dataSource name="binFileDataSource" type="BinFileDataSource"/>
<document>
<entity name="office-files" dataSource="fileDataSource" rootEntity="false" processor="FileListEntityProcessor" baseDir="c:/docs" fileName=".*\.(doc)|(docx)|(pdf)|(xls)|(xlsx)|(ppt)|(pptx)" recursive="true">
<entity name="tika-office-files" processor="TikaEntityProcessor" url="${office-files.fileAbsolutePath}" format="text" dataSource="binFileDataSource" onError="skip">
<field column="Author" name="author" meta="true"/>
<field column="title" name="title" meta="true"/>
<field column="text" name="text"/>
</entity>
</entity>
</document>
</dataConfig>
- 但值得注意的是,在实际测试当中发现solr-5.3.1只支持office2007之前的文件格式,即doc、xls、ppt,不支持docx、xlsx、pptx。
请在环境中导入以下三个jar包来实现office导入。
office依赖jar包
III.索引网络上的远程文件
索引单个URL
主要的配置改动依旧是data-config.xml,具体配置如下。
<dataConfig>
<dataSource name="urlDataSource" type="URLDataSource"/>
<document>
<entity processor="PlainTextEntityProcessor" name="onlineTxtFile" url="http://tech.163.com/15/0527/16/AQKTMJB0000915BF.html" dataSource="urlDataSource">
<field column="plainText" name="text"/>
</entity>
</document>
</dataConfig>
- 这里值得注意的是,在schema.xml中定义text域时,最好采用text_general类型,如果采用strings类型(该类型限定长度为32766字符)可能会因为数据超过限定长度而报错。
索引多个URL:通过url.txt文件声明需要索引的url列表,通过LineEntityProcessor读取资源访问列表,PlainTextEntityProcessor则依次读取由LineEntityProcessor获取的url来访问和索引数据。
- 同样,我们修改data-config.xml来实现以上功能。
<dataConfig>
<dataSource name="fileDataSource" type="FileDataSource"/>
<dataSource name="urlDataSource" type="URLDataSource"/>
<document>
<entity name="line" processor="LineEntityProcessor" acceptLineRegex="^.*\.shtml$" url="c:/docs/seed.txt" rootEntity="false" dataSource="fileDataSource">
<entity processor="PlainTextEntityProcessor" name="onlineTxtFile" url="${line.rawLine}" dataSource="urlDataSource">
<field column="plainText" name="text"/>
</entity>
</entity>
</document>
</dataConfig>
关于LineEntityProcessor的参数:
- 该处理器会读取文件每一行的内容,并将每一行的内容已rawLine为Key存入Map结构;
- 提供acceptLineRegex参数,表示当前行内容是否接受处理的正则表达式;
- 提供skipLineRegex参数,表示不符合次正则表达式的行将会被跳过不予处理;
- 如果读取到的当前行内容为null,则表明已经读取到文件末尾,直接跳出循环。所以,首行/中间行不能为空行,否则会直接返回null,导致前面的所有数据都读取失败。
- 我们在c:/docs下创建seed.txt,其内容如下
http://guba.sina.com.cn/?s=thread&bid=9279&tid=2257136&pid=1&dpc=1
https://finance.sina.com.cn/china/2019-02-15/doc-ihrfqzka6124881.shtml
https://finance.sina.com.cn/china/2019-02-15/doc-ihrfqzka6063381.shtml
https://finance.sina.com.cn/stock/jsy/2019-02-15/doc-ihqfskcp5467993.shtml
https://finance.sina.com.cn/roll/2019-02-15/doc-ihqfskcp5295349.shtml
http://blog.sina.com.cn/s/blog_1515cbfd80102yghf.html
- 执行dataimport中line实例后,将导入以.shtml结尾的资源数据索引。
IV.索引XML文件
非solr格式化的xml:采用xpath处理器
- 同样,我们需要更改data-config.xml配置,其内容如下,我们需要对Xpath语法有基本的了解。
<dataConfig>
<dataSource name="fileDataSource" type="FileDataSource" encoding="UTF-8"/>
<document>
<entity name="books" processor="XPathEntityProcessor" dataSource="fileDataSource" stream="true" forEach="/catalog/book" url="c:/docs/books.xml" transformer="DateFormatTransformer">
<field column="id" xpath="/catalog/book/@id" multiValued="false" flatten="true"/>
<field column="title" xpath="/catalog/book/title"/>
<field column="genre" xpath="/catalog/book/genre"/>
<field column="author" xpath="/catalog/book/author"/>
<field column="price" xpath="/catalog/book/price"/>
<field column="publishDate" xpath="/catalog/book/publish_date" dateTimeFormat="yyyy-MM-dd"/>
<field column="description" xpath="/catalog/book/description"/>
</entity>
</document>
</dataConfig>
- stream:表示是否另起线程采用队列分批处理,如果xml文件比较大,建议开启(设置为true)来提高效率;
- Transformer:数据格式转换器,这里用了DateFormatTransformer用来对publish_date的日期格式进行转换
- multiValued:表示这个域是否为多值域;
- flatten:表示如果当前xpath表达式定位到的元素下如果还有其他子元素,是否需要下面所有子元素的文本全部拼接在一起,然后追加到当前元素文本的后面,拼接后的整体作为当前域的域值;
- 在schema.xml中为以上属性建立对应的solr索引域。
<field name="id" type="string" indexed="true" stored="true" required="false" multiValued="false" />
<field name="genre" type="text_general" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="title" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="author" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="price" type="float" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="publishDate" type="tdate" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="description" type="text_general" indexed="true" stored="true" required="false" multiValued="false"/>
- 将books.xml拷贝到c:/docs目录下,其内容如下。
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<book id="bk001">
<author>Author1</author>
<title>XMLDeveloper</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-01-01</publish_date>
<description>This is an demo description1</description>
</book>
<book id="bk002">
<author>Author2</author>
<title>Effective Java</title>
<genre>Computer Science</genre>
<price>59.00</price>
<publish_date>2019-01-01</publish_date>
<description>This is an demo description2</description>
</book>
</catalog>
-
通过dataimport中books实例,执行导入。
books导入 - 成功导入后,就可以在solr控制台查询到相关数据。
查询结果
solr格式化的xml
1.我们修改data-config.xml,因为这种solr格式化的xml我们之前也使用过,对于这类符合solr格式化的xml,配置文件的配置方法也相比之前的方式更加简洁。
<dataConfig>
<dataSource name="fileDataSource" type="FileDataSource" encoding="UTF-8"/>
<document>
<entity name="money" processor="XPathEntityProcessor" dataSource="fileDataSource" stream="true" useSolrAddSchema="true" forEach="/catalog/book" url="c:/docs/money.xml" transformer="DateFormatTransformer">
</entity>
</document>
</dataConfig>
这里的关键在于参数useSolrAddSchema,当xml符合solr格式的时候,我们就不需要手动去对field进行映射。
- 同时,我们对schema.xml进行修改,映射到xml对应的域。
<field name="id" type="string" indexed="true" stored="true" required="false" multiValued="false" />
<field name="name" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="menu" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="manu_id_s" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="cat" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="features" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="price" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
<field name="inStock" type="string" indexed="true" stored="true" required="false" multiValued="false"/>
- 拷贝money.xml到c:/docs目录下,其内容如下。
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Example documents utilizing the CurrencyField type -->
<add>
<doc>
<field name="id">USD</field>
<field name="name">One Dollar</field>
<field name="manu">Bank of America</field>
<field name="manu_id_s">boa</field>
<field name="cat">currency</field>
<field name="features">Coins and notes</field>
<field name="price_c">1,USD</field>
<field name="inStock">true</field>
</doc>
<doc>
<field name="id">EUR</field>
<field name="name">One Euro</field>
<field name="manu">European Union</field>
<field name="manu_id_s">eu</field>
<field name="cat">currency</field>
<field name="features">Coins and notes</field>
<field name="price_c">1,EUR</field>
<field name="inStock">true</field>
</doc>
<doc>
<field name="id">GBP</field>
<field name="name">One British Pound</field>
<field name="manu">U.K.</field>
<field name="manu_id_s">uk</field>
<field name="cat">currency</field>
<field name="features">Coins and notes</field>
<field name="price_c">1,GBP</field>
<field name="inStock">true</field>
</doc>
<doc>
<field name="id">NOK</field>
<field name="name">One Krone</field>
<field name="manu">Bank of Norway</field>
<field name="manu_id_s">nor</field>
<field name="cat">currency</field>
<field name="features">Coins and notes</field>
<field name="price_c">1,NOK</field>
<field name="inStock">true</field>
</doc>
</add>
4.接下来的步骤与前者相同,不再赘述。