3

假设我有两种 XML 文档类型,A 和 B,如下所示:

A:

<xml>
    <a>
        <name>First Number</name>
        <num>1</num>
    </a>
    <a>
        <name>Second Number</name>
        <num>2</num>
    </a>
</xml>

乙:

<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>

但是,我遇到两个问题:

  1. 我无法获得带有谓词的 XPath 表达式来匹配任何行;无论我是否使用类似的替代方法/xml/b[aKey=${a.num}]/value,甚至是硬编码的值aKey
  2. 即使我删除了谓词,解析器也会为 A 中的每一行遍历 B 文件一次,这显然是低效的。

我的问题是:鉴于上面列出的问题,我如何使用 DataImportHandler 正确有效地索引数据

我正在使用 Solr 3.6.2 。

注意:这有点类似于这个问题,但它处理两种 XML 文档类型,而不是 RDBMS 和 XML 文档。

4

2 回答 2

2

我在使用 DataImportHandler 处理这类数据时有非常糟糕的经历。一个用于合并数据的简单 Python 脚本可能会比您当前的配置更小,并且更具可读性。根据您的要求和数据大小,您可以创建一个临时 xml 文件,也可以将结果直接通过管道传输到 SOLR。如果你真的必须使用 DataImportHandler,你可以使用 URLDataSource 并设置一个最小的服务器来生成你的 xml。Obvioulsy 我是 Python 的粉丝,但它很可能在 Ruby、Perl、...

于 2013-05-20T21:03:30.050 回答
0

由于我最初没有提到的额外设计要求,我最终选择了另一种解决方案。接下来是解释和讨论。所以....

如果您的 Solr 实例只有一种或几种导入流类型:

那么最好使用Achim 的答案并开发您自己的导入器 - 正如 Achim 建议的那样,使用您最喜欢的脚本语言,或者在 Java 中使用SolrJ 的 ConcurrentUpdateSolrServer.

这是因为一旦您需要定义更复杂的导入流程,DataImportHandler 框架的学习曲线就会突然飙升。

如果您有大量不同的导入流:

然后我建议您考虑使用 DataImportHandler,因为您可能最终会实现类似的东西。而且,由于该框架非常模块化和可扩展,因此定制不是问题。

这是我提到的附加要求,所以最后我选择了那条路线。

我如何解决我的特殊难题是将我需要引用的文件索引到单独的核心中,并使用修改后SolrEntityProcessor的数据来访问该数据。修改如下:

  • 为子实体问题应用补丁,
  • 添加缓存(使用 Guava 的快速解决方案,可能有更好的方法使用可用的 Solr API 在本地访问其他内核,但当时我有点着急)。

如果您不想为每个文件创建一个新核心,另一种选择是对 Achim 的想法进行扩展,即创建一个自定义EntityProcessor来预加载数据并启用以某种方式对其进行查询。

于 2013-06-05T19:40:34.507 回答