XML/HTTP Datasource使用指南

DataImportHandler 能够帮我们为基于HTTP的数据源建立索引. 目前支持REST/XML APIs 和RSS/ATOM Feeds.

配置HttpDataSource

HttpDataSource在dataconfig.xml中的配置看起来应该像这样: 


<dataSource type="HttpDataSource" baseUrl="http://host:port/" encoding="UTF-8" connectionTimeout="5000" readTimeout="10000"/>



属性:

  • baseUrl (可选): 在Dev/QA/Prod 环境中,host/port改变时,你会用到它。使用这个属性,你可以找出配置到solrconfig.xml的变化。
  • encoding(可选): 默认情况下,encoding是response 头使用的encoding.你可以使用这个属性去覆盖默认值。
  • connectionTimeout (可选):默认值是5000ms
  • readTimeout (可选): 默认值是10000ms

在 data-config.xml中的配置

 一个 xml/http data source中的实体有下面一些属性,也可以有上面提到的默认属性。

  • processor (必需的) : 它的值应该是"XPathEntityProcessor"
  • url (必需的) :  REST API要使用这个api. (能够被模板化). 假设数据源是一个文件,那么url应该是这个文件的位置。
  • stream (可选) : 如果xml很大,那么它应该设为true
  • forEach(必需的) : xpath表达式,通过这个表达式可以取得想要的值。如果这里有多个想要的值,那么将xpath表达式用“|”分开。如果useSolrAddSchema设为true的话,这个是可以被忽略的。
  • xsl(可选):使用xsl对xml进行预处理。你需要提供一个文件系统的全路径,或者一个url。
  • useSolrAddSchema(可选): Set it's value to 'true' if the xml that is fed into this processor has the same schema as that of the solr add xml. No need to mention any fields if it is set to true.

域能够有以下这些属性 (此外还有那些默认值):

  • xpath (必需的) : 记录中的一列,也就是域的xpath表达式 . 如果该域并不来自任何的一个单一的xml属性,xpath是可以被忽略的. 我们可以通过转化器来使用多个xml属性来合成该域。如果一个域被声明成多值的,如果xpath表达式生成的也是多值的,那么XPathEntityProcessor将会自动处理它,而不需要我们做额外的工作。
  • commonField : 能够被设为(true或者false),假设这个是true值,一旦一个记录中有这样的域,那么其他记录被写索引的时候,这个域也会跟着记录被写到索引里面。

如果一个API支持分块数据(当一个数据集太大时),可能需要多次调用才能完成这个处理过程。XPathEntityprocessor 通过转换器支持这个特性。如果转换器返回的的行带有属性“hasMore”,并且这个属性的值等于true,那么Processor 将会使用同样的url模板发出令一次请求(实际的url是需要重新计算的)。一个转换器也可以传递一个完整的url路径,这个url被包含在属性“nextUrl”中,nextUrl的值必需是一个完整的url。

XPathEntityProcessor 通过实现streaming parser来支持取得xpath子集的操作。完整的xpath是不被支持的,但是常见的应用都是受支持的。

HttpDataSource 例子

下载 在DB 部分中的“完全导入”例子,试着去体验一下。我们将在这里例子中为slashotRSS建立索引。

这个例子的data-config配置看起来像这样。


<dataConfig> <dataSource type="HttpDataSource" /> <document> <entity name="slashdot" pk="link" url="http://rss.slashdot.org/Slashdot/slashdot" processor="XPathEntityProcessor" forEach="/RDF/channel | /RDF/item" transformer="DateFormatTransformer"> <field column="source" xpath="/RDF/channel/title" commonField="true" /> <field column="source-link" xpath="/RDF/channel/link" commonField="true" /> <field column="subject" xpath="/RDF/channel/subject" commonField="true" /> <field column="title" xpath="/RDF/item/title" /> <field column="link" xpath="/RDF/item/link" /> <field column="description" xpath="/RDF/item/description" /> <field column="creator" xpath="/RDF/item/creator" /> <field column="item-subject" xpath="/RDF/item/subject" /> <field column="date" xpath="/RDF/item/date" dateTimeFormat="yyyy-MM-dd'T'hh:mm:ss" /> <field column="slash-department" xpath="/RDF/item/department" /> <field column="slash-section" xpath="/RDF/item/section" /> <field column="slash-comments" xpath="/RDF/item/comments" /> </entity> </document> </dataConfig>


这个data-config有很多值得借鉴的地方。 我建议你看下SlashdotRSS的结构图,它有一些头部元素,例如title、link、subject。这些元素将分别通过xpath语法映射到source、source-link、subject这些solr域。这个种子有多个item元素,这些元素包含了真正的新闻信息。所以,我们希望做得是,为每一个item元素建立一个文档。


XPathEntityprocessor 是一行一行的读取xml文件的(这里的行指的是一个xml元素)。它使用属性“forEach”去识别每一行 。在这个例子一种“forEach”的值是'/RDF/channel | /RDF/item'。也就是说这个xml有两种类型的行(这里使用一个OR的xpath语法,用以支持多个类型) 。当遇到一个行的时候,它会在行的域声明中读取尽量多的域。在这个例子中,当它读到行“/RDF/channel”时,它将会得到3个域。它处理完这个行的时候,它就会意识到,这个行并没有pk这个域的值,于是它并不会试图去建立一个solr文档(即使它去做,它也会失败)。但是这个三个域都有一个属性commonField ,并且它的值是true,所以它将会保留这个域的值,以便后面的行可以使用

它继续前进,然后遇到/RDF/item ,接着一个个处理这些行。它将会取得除了那个三个域之外的所有域。但是因为他们是common field。处理器会把公共域也加到这个记录中,然后写入索引。

transformer=DateFormatTransformer 又是什么呢?你可以看一下DateFormatTransformer有关部分。

你可以使用这些特性来从REST API ,例如 rss、atom、xml、其他solr服务器、甚至是格式良好的xhtml文档,建立索引。我们的xpath语法有它自己的限制(不支持通配符,只可以是全路径),但是一般的应用是绝对没有问题的,而且它是基于streaming parser的,它非常快,并且在读取非常大的xml文件的时候,它的内存消耗始终保持如一。它不支持命名空间,它却可以处理带有命名空间的xml文件。当你处理带有命名空间的xpath的时候,你需要做的是,丢弃命名空间部分,只留下其他的部分(例如,这个标签,相对应的xpath部分是subject)。很容易,是吧?而且你不需要写一行代码,好好享受吧。

 注意 : 不像数据库,如果你使用XPathEntityProcessor,想忽略域声明是不可能。域通过你声明的xpaths来从xml中解析相应的数据。

 

例子: 索引 wikipedia

利用下面的data-config.xml文件可以对wikipedia的数据建立索引。从wikipedia下载下来的pages-articles.xml.bz2文件解压之后大概有18g。


<dataConfig> <dataSource type="FileDataSource" encoding="UTF-8" /> <document> <entity name="page" processor="XPathEntityProcessor" stream="true" forEach="/mediawiki/page/" url="/data/enwiki-20080724-pages-articles.xml"> <field column="id" xpath="/mediawiki/page/id" /> <field column="title" xpath="/mediawiki/page/title" /> <field column="revision" xpath="/mediawiki/page/revision/id" /> <field column="user" xpath="/mediawiki/page/revision/contributor/username" /> <field column="userId" xpath="/mediawiki/page/revision/contributor/id" /> <field column="text" xpath="/mediawiki/page/revision/text" /> <field column="timestamp" xpath="/mediawiki/page/revision/timestamp" /> </entity> </document> </dataConfig>


schema.xml中有关的部分如下所示:


<field name="id" type="integer" indexed="true" stored="true" required="true"/> <field name="title" type="string" indexed="true" stored="false"/> <field name="revision" type="sint" indexed="true" stored="true"/> <field name="user" type="string" indexed="true" stored="true"/> <field name="userId" type="integer" indexed="true" stored="true"/> <field name="text" type="text" indexed="true" stored="false"/> <field name="timestamp" type="date" indexed="true" stored="true"/> <field name="titleText" type="text" indexed="true" stored="true"/> ... <uniqueKey>id</uniqueKey> <copyField source="title" dest="titleText"/>

为7278241个文章建立索引大概花了2个小时40分,内存使用量的峰值在4G左右。

使用“增量导入”命令

只有SqlEntitiProcessor支持增量数据!XPathEntityProcessor还没有实现它。所以,不幸运的是,现在还不能为“增量导入”提供支持。如果你想要在XPathEntityProcessor中实现这些方法,你可以在EntityProcessor.java中看看这些方法的解释。

英文原文:http://wiki.apache.org/solr/DataImportHandler