假设我有两种XML文档类型,A和B,如下所示:
A:
<xml>
<a>
<name>First Number</name>
<num>1</num>
</a>
<a>
<name>Second Number</name>
<num>2</num>
</a>
</xml>
B:
<xml>
<b>
<aKey>1</aKey>
<value>one</value>
</b>
<b>
<aKey>2</aKey>
<value>two</value>
</b>
</xml>
我想像这样索引它:
<doc>
<str name="name">First Name</str>
<int name="num">1</int>
<str name="spoken">one</str>
</doc>
<doc>
<str name="name">Second Name</str>
<int name="num">2</int>
<str name="spoken">two</str>
</doc>
所以,实际上,我正在尝试使用A中的值作为B中的键 . 使用DataImportHandler,我使用以下作为我的数据配置定义:
<dataConfig>
<dataSource type="FileDataSource" encoding="UTF-8" />
<document>
<entity name="document" transformer="LogTransformer" logLevel="trace"
processor="FileListEntityProcessor" baseDir="/tmp/somedir"
fileName="A.*.xml$" recursive="false" rootEntity="false"
dataSource="null">
<entity name="a"
transformer="RegexTransformer,TemplateTransformer,LogTransformer"
logLevel="trace" processor="XPathEntityProcessor" url="${document.fileAbsolutePath}"
stream="true" rootEntity="true" forEach="/xml/a">
<field column="name" xpath="/xml/a/name" />
<field column="num" xpath="/xml/a/num" />
<entity name="b" transformer="LogTransformer"
processor="XPathEntityProcessor" url="/tmp/somedir/b.xml"
stream="false" forEach="/xml/b" logLevel="trace">
<field column="spoken" xpath="/xml/b/value[../aKey=${a.num}]" />
</entity>
</entity>
</entity>
</document>
</dataConfig>
但是,我遇到两个问题:
-
我无法使用谓词来获取XPath表达式以匹配任何行;无论我是否使用像
/xml/b[aKey=${a.num}]/value
这样的替代品,或者甚至是aKey
的硬编码值 . -
即使我删除了谓词,解析器也会为A中的每一行遍历B文件一次,这显然是低效的 .
我的问题是: how, in light of the problems listed above, do I index the data correctly and efficiently with the DataImportHandler ?
我正在使用Solr 3.6.2 .
注意:这有点类似于this question,但它处理两种XML文档类型而不是RDBMS和XML文档 .
2 回答
对于那种数据,我使用DataImportHandler的经历非常糟糕 . 用于合并数据的简单python脚本可能比您当前的配置小,而且更具可读性 . 根据您的要求和数据大小,您可以创建临时xml文件,也可以直接将结果传递给SOLR . 如果您真的必须使用DataImportHandler,则可以使用URLDataSource并设置生成xml的最小服务器 . Obvioulsy我是Python的粉丝,但很可能它在Ruby,Perl,...中也很容易 .
由于我最初没有提到的额外设计要求,我终于选择了另一种解决方案 . 以下是解释和讨论 . 所以....
如果您的Solr实例只有一个或几个导入流类型:
然后最好与Achim's answer一起开发自己的导入器 - 正如Achim建议的那样,使用您最喜欢的脚本语言,或者使用SolrJ的
ConcurrentUpdateSolrServer
.这是因为一旦您需要定义更复杂的导入流,DataImportHandler框架的学习曲线就会突然出现峰值 .
如果您有不同数量的不同导入流程:
然后我建议你考虑使用 you will probably end up implementing something similar anyway 以后的DataImportHandler . 而且,由于框架非常模块化和可扩展,因此定制不是问题 .
这是我提到的额外要求,所以最后我选择了这条路线 .
我如何解决我的特殊困境是将我需要引用的文件编入索引到单独的内核并使用修改后的
SolrEntityProcessor
来访问该数据 . 修改如下:应用sub-entity problem的补丁,
添加缓存(使用Guava的快速解决方案,可能有更好的方法使用可用的Solr API在本地访问其他核心,但我在这一点上有点匆忙) .
如果您没有想法,即创建一个自定义
EntityProcessor
,它将预加载数据并以某种方式启用查询 .