Solr使用索引处理程序上传数据

2018-11-21 15:07 更新

索引处理程序是一种请求处理程序,旨在添加、删除和更新文件到索引。除了使用 Tika 导入丰富文档的插件或使用数据导入处理程序的结构化数据源外,Solr 本身还支持以 XML、CSV 和 JSON 中的结构化文档索引。

建议配置和使用请求处理程序的方法是使用基于路径的名称映射到请求 url 中的路径。但是,如果正确配置了 requestDispatcher,则也可以使用 qt(查询类型)参数指定请求处理程序。可以使用多个名称来访问相同的处理程序,如果您希望指定不同的默认选项集,这可能很有用。

一个统一的更新请求处理程序支持 XML、CSV、JSON 和 javabin 更新请求,并根据 ContentStream 的内容类型委派给适当的 ContentStreamLoader。

UpdateRequestHandler 配置

默认配置文件具有默认配置的更新请求处理程序。

<requestHandler name="/update" class="solr.UpdateRequestHandler" />

XML 格式化索引更新

索引更新命令可以使用 Content-type: application/xml 或者 Content-type: text/xml 作为 XML 消息发送到更新处理程序。

添加文档

由更新处理程序识别的用于添加文档的 XML 架构非常简单:

  • <add> 元素引入了一个要添加的文档。
  • <doc> 元素引入了组成文档的字段。
  • <field> 元素显示具有特定领域的内容。

例如:

<add>
  <doc>
    <field name="authors">Patrick Eagar</field>
    <field name="subject">Sports</field>
    <field name="dd">796.35</field>
    <field name="numpages">128</field>
    <field name="desc"></field>
    <field name="price">12.40</field>
    <field name="title">Summer of the all-rounder: Test and championship cricket in England 1982</field>
    <field name="isbn">0002166313</field>
    <field name="yearpub">1982</field>
    <field name="publisher">Collins</field>
  </doc>
  <doc>
  ...
  </doc>
</add>

add 命令支持一些可以指定的可选属性。

commitWithin

在指定的毫秒数内添加文档。

overwrite

默认是 true。指示是否应检查唯一键约束以覆盖同一文档的以前版本(请参见下文)。

如果文档架构定义了唯一的键,那么默认情况下,添加文档的 /update 操作将使用相同的唯一键覆盖(即替换)索引中的任何文档。如果没有定义唯一的键,索引性能会更快一些,因为不需要对现有文档进行任何检查来替换。

如果您有一个唯一的关键字段,但您确信您可以安全地绕过唯一性检查(例如,在批处理中生成索引,并且索引代码保证它从不多次添加同一文档),您可以指定overwrite="false" 选项当您添加您的文档时。

XML 更新命令

在更新期间提交和优化

该 <commit> 操作将自从上次提交后加载的所有文档写入磁盘上的一个或多个段文件。在提交之前,新索引的内容对于搜索是不可见的。提交操作将打开一个新的搜索器,并触发已配置的任何事件侦听器。

可以使用 <commit/> 消息显式发出提交,也可以在 solrconfig. xml 中触发 <autocommit> 参数。

该 <optimize> 操作请求 Solr 合并内部数据结构以提高搜索性能。对于大型索引,优化需要一些时间才能完成,但是通过将许多小段文件合并为一个更大的文件,搜索性能将会提高。如果您使用 Solr 的复制机制在多个系统上分发搜索,请注意,在进行优化之后,需要传输一个完整的索引。相比之下,提交后的转移通常要小得多。

在 <commit> 和 <optimize> 元素中接受这些可选属性:

waitSearcher

默认是 true。阻塞,直到打开新的搜索器并注册为主查询搜索器,使更改可见。

expungeDeletes

(只提交)默认是 false。合并超过10%已删除文档的细分受众群,并在此过程中将其删除。

maxSegments

(仅限优化)默认是1。将分段合并到不超过此段数量。

以下是使用 <commit> 和 <optimize> 可选属性的示例:

<commit waitSearcher="false"/>
<commit waitSearcher="false" expungeDeletes="true"/>
<optimize waitSearcher="false"/>

删除操作

文件可以通过两种方式从索引中删除。“按 ID 删除”删除具有指定 ID 的文档,只有在架构中定义了 UniqueID 字段时才能使用。“按查询删除”会删除与指定查询匹配的所有文档,但 commitWithin 对于按查询删除而言将被忽略。单个删除消息可以包含多个删除操作。

<delete>
  <id>0002166313</id>
  <id>0031745983</id>
  <query>subject:sport</query>
  <query>publisher:penguin</query>
</delete>
注意:在 Delete By Query(按查询删除)中使用 Join 查询解析器时,应该使用值为 “none” 的 score 参数来避免 ClassCastException。有关 score 参数的更多详细信息,请参见 Join Query Parser(联接查询分析器)部分。

回滚操作

回滚命令将回滚自上次提交以来对索引所做的所有添加和删除操作。它既不调用任何事件侦听器也不创建新的搜索器。它的语法很简单:<rollback/>。

使用 curl 来执行更新

您可以使用 curl 实用程序执行上述任何命令,使用其 --data-binary 选项将 XML 消息附加到 curl 命令,并生成 HTTP POST 请求。例如:

curl http://localhost:8983/solr/my_collection/update -H "Content-Type: text/xml" --data-binary '
<add>
  <doc>
    <field name="authors">Patrick Eagar</field>
    <field name="subject">Sports</field>
    <field name="dd">796.35</field>
    <field name="isbn">0002166313</field>
    <field name="yearpub">1982</field>
    <field name="publisher">Collins</field>
  </doc>
</add>'

要发布文件中包含的 XML 消息,可以使用其他形式:

curl http://localhost:8983/solr/my_collection/update -H "Content-Type: text/xml" --data-binary @myfile.xml

也可以使用 HTTP GET 命令发送短请求(如果在 SolrConfig 元素中的 RequestDispatcher 中启用),请对 URL 进行编码,如下所示。注意"<" and ">"的转义:

curl http://localhost:8983/solr/my_collection/update?stream.body=%3Ccommit/%3E

Solr 的回应采取如下所示的形式:

<response>
  <lst name="responseHeader">
    <int name="status">0</int>
    <int name="QTime">127</int>
  </lst>
</response>

在失败的情况下,状态字段将是非零的。

使用 XSLT 转换 XML 索引更新

UpdateRequestHandler 允许您使用 <tr> 参数来应用 XSL 转换来索引任意 XML。您必须在配置集的 conf/xslt 目录中有一个 XSLT 样式表,可以将传入的数据转换为预期的 <add><doc/></add> 格式,并使用 tr 参数指定该样式表的名称。

下面是一个 XSLT 样式表示例:

<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
  <xsl:output media-type="text/xml" method="xml" indent="yes"/>
  <xsl:template match='/'>
    <add>
      <xsl:apply-templates select="response/result/doc"/>
    </add>
  </xsl:template>
  <!-- Ignore score (makes no sense to index) -->
  <xsl:template match="doc/*[@name='score']" priority="100"></xsl:template>
  <xsl:template match="doc">
    <xsl:variable name="pos" select="position()"/>
    <doc>
      <xsl:apply-templates>
        <xsl:with-param name="pos"><xsl:value-of select="$pos"/></xsl:with-param>
      </xsl:apply-templates>
    </doc>
  </xsl:template>
  <!-- Flatten arrays to duplicate field lines -->
  <xsl:template match="doc/arr" priority="100">
    <xsl:variable name="fn" select="@name"/>
    <xsl:for-each select="*">
      <xsl:element name="field">
        <xsl:attribute name="name"><xsl:value-of select="$fn"/></xsl:attribute>
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="doc/*">
    <xsl:variable name="fn" select="@name"/>
      <xsl:element name="field">
        <xsl:attribute name="name"><xsl:value-of select="$fn"/></xsl:attribute>
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>
  <xsl:template match="*"/>
</xsl:stylesheet>

此样式表将 Solr 的 XML 搜索结果格式转换为 Solr 的更新 XML 语法。一个示例用法是将 Solr 1.3 索引(没有 CSV 响应编写器)复制为可以索引到另一个 Solr 文件中的格式(前提是所有字段都存储):

http://localhost:8983/solr/my_collection/select?q=*:*&wt=xslt&tr=updateXml.xsl&rows=1000

XsltUpdateRequestHandler 更新时也可以使用样式表来转换索引:

curl "http://localhost:8983/solr/my_collection/update?commit=true&tr=updateXml.xsl" -H "Content-Type: text/xml" --data-binary @myexporteddata.xml

JSON 格式化索引更新

Solr 可以接受符合定义结构的 JSON,或者可以接受任意的 JSON 格式的文档。如果发送任意格式的 JSON,则需要使用更新请求发送一些其他参数,如下面的“自定义JSON 转换和索引”部分所述。

Solr 风格的 JSON

JSON 格式的更新请求可以使用 Content-Type: application/json 或 Content-Type: text/json 发送到 Solr 的 /update 处理程序。

JSON 格式的更新可以采取 3 种基本形式,下面进行深入的描述:

  • 要添加的单个文档,表示为顶级 JSON 对象。为了区分这一点与一组命令,json.command=false 请求参数是必需的。
  • 要添加的文档列表,表示为包含每个文档的 JSON 对象的顶级 JSON 数组。
  • 一系列更新命令,表示为顶级 JSON 对象(又名:Map)。

添加一个 JSON 文档

通过 JSON 添加文档的最简单方法是使用以下 /update/json/docs 路径将每个文档分别作为 JSON 对象单独发送:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_collection/update/json/docs' --data-binary '
{
  "id": "1",
  "title": "Doc 1"
}'

添加多个 JSON 文档

通过 JSON 一次添加多个文档可以通过 JSON 对象的 JSON 数组完成,其中每个对象都代表一个文档:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_collection/update' --data-binary '
[
  {
    "id": "1",
    "title": "Doc 1"
  },
  {
    "id": "2",
    "title": "Doc 2"
  }
]'

一个示例 JSON 文件提供的 example/exampledocs/books.json 并包含可添加到 Solr techproducts 示例的对象数组:

curl 'http://localhost:8983/solr/techproducts/update?commit=true' --data-binary @example/exampledocs/books.json -H 'Content-type:application/json'

发送 JSON 更新命令

发送 JSON 更新命令通常, JSON 更新语法通过简单的映射支持 XML 更新处理程序支持的所有更新命令。多条命令、添加和删除文档可能包含在一条消息中:

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_collection/update' --data-binary '
{
  "add": {
    "doc": {
      "id": "DOC1",
      "my_field": 2.3,
      "my_multivalued_field": [ "aaa", "bbb" ]【1】   
    }
  },
  "add": {
    "commitWithin": 5000, 【2】
    "overwrite": false,  【3】
    "doc": {
      "f1": "v1", 【4】
      "f1": "v2"
    }
  },

  "commit": {},
  "optimize": { "waitSearcher":false },

  "delete": { "id":"ID" },  【5】
  "delete": { "query":"QUERY" } 【6】
}'

以下解释对应于上述代码:

  1. 可以对多值字段使用数组
  2. 在5秒内提交此文档
  3. 不要使用相同的 uniqueKey 检查现有文档
  4. 可以对多值字段使用重复键
  5. 按 ID 删除 (uniqueKey 字段)
  6. 按查询删除

与其他更新处理程序一样,可以在 URL 而不是消息正文中指定诸如 commit、commitWithin、optimize 和 overwrite 等参数。

JSON 更新格式允许简单的删除 ID。delete 的值可以是一个数组,其中包含零个或多个特定文档 ID(不是范围)的要删除的列表。例如,单个文档:

{ "delete":"myid" }

或文档 ID 的列表:

{ "delete":["id1","id2"] }

“delete”的值可以是包含要删除的零个或多个 ID 的列表的数组。这不是一个范围(开始和结束)。

您也可以使用每个“delete” 指定  _version_ :

{
  "delete":"id":50,
  "_version_":12345
}

您也可以在更新请求的主体中指定删除的版本。

JSON 更新便利路径

除了 /update 处理程序之外,Solr 中默认还有一些额外的 JSON 特定的请求处理程序路径,它隐式覆盖了一些请求参数的行为:

路径 默认参数

/update/json

stream.contentType=application/json

/update/json/docs

stream.contentType=application/json

json.command=false

该 /update/json 路径对于从设置 Content-Type 的应用程序中发送 JSON 格式的更新命令的客户端来说非常有用,因为设置 Content-Type 的应用程序证明是困难的,而 /update/json/docs 路径对于总是希望单独发送或作为列表发送文档的客户端而言,可能是特别方便的,无需担心完整的 JSON 命令语法。

自定义 JSON 文档

Solr 可以支持自定义的 JSON。这在 “自定义 JSON 转换和索引” 部分中进行了介绍。

CSV 格式索引更新

CSV 格式的更新请求可以使用 Content-Type: application/csv 或 Content-Type: text/csv 发送到 Solr 的 /update 处理程序。

一个示例 CSV 文件提供了 example/exampledocs/books.csv,您可以使用它将一些文档添加到 Solr techproducts 示例中:

curl 'http://localhost:8983/solr/my_collection/update?commit=true' --data-binary @example/exampledocs/books.csv -H 'Content-type:application/csv'

CSV 更新参数

该 CSV 处理程序允许在表单中的 URL 中的 f.parameter.optional_fieldname=value 指定许多参数。

下表介绍了更新处理程序的参数。

separator

用作字段分隔符的字符;默认是“,”。这个参数是全局的;对于每个字段的使用情况,请参阅split参数。

例:separator=%09

trim

如果true从值中删除前导和尾随空白。默认是false。此参数可以是全局或每个字段。

例子:f.isbn.trim=truetrim=false

header

如果输入的第一行包含字段名称,则设置为 true;如果fieldnames参数不存在,将使用这些参数。这个参数是全局的。

fieldnames

添加文档时使用逗号分隔的字段名称列表。这个参数是全局的。

例:fieldnames=isbn,price,title

literal.field_name

指定字段名称的文字值。这个参数是全局的。

例:literal.color=red

skip

逗号分隔的字段名称列表跳过。这个参数是全局的。

例:skip=uninteresting,shoesize

skipLines

在 CSV 数据开始之前在输入流中放弃的行数,包括标题(如果存在)。默认 = 0。这个参数是全局的。

例:skipLines=5

encapsulator

字符可选用于包围值以保留字符(如 CSV 分隔符或空格)。这个标准的 CSV 格式通过加倍封装器来处理出现在封装值中的封装器本身。

这个参数是全局的;有关每个字段的使用情况,请参阅split

例:encapsulator="

escape

用于转义 CSV 分隔符或其他保留字符的字符。如果指定了转义,则除非明确指定,否则不使用封装器,因为大多数格式使用封装或转义,而不是两种方式。

      例: escape=\

keepEmpty

保留和索引零长度(空)字段。默认是false。此参数可以是全局或每个字段。

例:f.price.keepEmpty=true

map

将一个值映射到另一个值。格式是 value:replacement(可以是空的)。此参数可以是全局或每个字段。

例如:map=left:rightf.subject.map=history:bunk

split

如果true通过单独的解析器将字段分成多个值。该参数在每个字段的基础上使用。

overwrite

如果true(默认),根据 Solr 模式中声明的 uniqueKey 字段检查并覆盖重复的文档。如果您知道索引的文档不包含任何重复内容,那么您可能会看到相当快的速度false

这个参数是全局的。

commit

数据摄取后发出提交。这个参数是全局的。

commitWithin

在指定的毫秒数内添加文档。这个参数是全局的。

例:commitWithin=10000

rowid

rowid(行号)映射到由参数的值指定的字段,例如,如果您的 CSV 没有唯一键,并且您想要使用行标识。这个参数是全局的。

例:rowid=id

rowidOffset

将给定的偏移量(作为整数)rowid添加到文档之前。默认是0。这个参数是全局的。

例:rowidOffset=10

索引制表符分隔的文件

用于索引 CSV 文档的相同功能也可以轻松用于索引制表符分隔的文件(TSV 文件),甚至可以处理反斜杠转义而不是 CSV 封装。

例如,可以使用以下命令将 MySQL 表转储到制表符分隔的文件中:

SELECT * INTO OUTFILE '/tmp/result.txt' FROM mytable;

然后可以通过将分隔符设置为 tab(%09)和 转义符(%5c)将该文件导入到 Solr 。

curl 'http://localhost:8983/solr/my_collection/update/csv?commit=true&separator=%09&escape=%5c' --data-binary @/tmp/result.txt

CSV 更新便利路径

除了 /update 处理程序之外,Solr 中默认还有一个额外的 CSV 特定请求处理程序路径,它隐式地覆盖了一些请求参数的行为:

路径 默认参数

/update/csv

stream.contentType=application/csv

该 /update/csv 路径对于客户端发送 CSV 格式的更新命令来说很有用,这些应用程序设置 Content-Type 非常困难。

嵌套的子文档

Solr将嵌套的文档嵌套在块中,以将包含其他文档的文档(比如一个 blog post 父文档和注释作为子文档)或作为父文档和大小、颜色或其他变体的子文档作为子文档来建模文档。在查询时,块联接查询解析器( Block Join Query Parsers)可以搜索这些关系。就性能而言,索引文档之间的关系可能比试图仅在查询时进行连接更有效率,因为关系已经存储在索引中并且不需要被计算。

嵌套文档可以通过 XML 或 JSON 数据语法(或使用 SolrJ)进行索引- 但是不管语法如何,您都必须包含一个将父文档标识为父项的字段;它可以是适合这个目的的任何字段,它将被用作块连接查询解析器的输入。

为了支持嵌套文档,架构必须包含 indexed/non-stored 字段_root_。无论继承深度如何,该字段的值都会自动填充,并且与块中的所有文档相同。

XML 示例

例如,这里有两个文件及其子文件:

<add>
  <doc>
  <field name="id">1</field>
  <field name="title">Solr adds block join support</field>
  <field name="content_type">parentDocument</field>
    <doc>
      <field name="id">2</field>
      <field name="comments">SolrCloud supports it too!</field>
    </doc>
  </doc>
  <doc>
    <field name="id">3</field>
    <field name="title">New Lucene and Solr release is out</field>
    <field name="content_type">parentDocument</field>
    <doc>
      <field name="id">4</field>
      <field name="comments">Lots of new features</field>
    </doc>
  </doc>
</add>

在这个例子中,我们使用字段 content_type 索引父文档,它具有值 “parentDocument”。我们也可以使用一个布尔型的字段,比如 isParent 值为 “true”,或者其他类似的方法。

JSON 示例

这个例子相当于上面的 XML 例子,请注意特殊的 _childDocuments_ 键需要指示 JSON 中的嵌套文档。

[
  {
    "id": "1",
    "title": "Solr adds block join support",
    "content_type": "parentDocument",
    "_childDocuments_": [
      {
        "id": "2",
        "comments": "SolrCloud supports it too!"
      }
    ]
  },
  {
    "id": "3",
    "title": "New Lucene and Solr release is out",
    "content_type": "parentDocument",
    "_childDocuments_": [
      {
        "id": "4",
        "comments": "Lots of new features"
      }
    ]
  }
]

注意:对嵌套文档进行索引的一个限制是,在需要进行任何更改时,必须将整个父子文档块一起更新。换言之,即使更改了单个子文档或父文档,也必须将整个父子文档块编入索引。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号