使用更新处理器进行索引

更新处理器是专为向索引添加、删除和更新文档而设计的请求处理器。除了具有用于导入丰富文档的插件(请参阅 使用 Solr Cell 和 Apache Tika 进行索引)之外,Solr 本机支持以 XML、CSV 和 JSON 格式索引结构化文档。

配置和使用请求处理器的推荐方法是使用基于路径的名称,这些名称映射到请求 URL 中的路径。但是,如果 requestDispatcher 进行了适当的配置,也可以使用 qt(查询类型)参数指定请求处理器。可以使用多个名称访问同一个处理器,如果您希望指定不同的默认选项集,这将非常有用。

一个统一的更新请求处理器支持 XML、CSV、JSON 和 javabin 更新请求,根据 ContentStreamContent-Type 将其委托给相应的 ContentStreamLoader

如果您需要在加载文档后但在索引文档之前(甚至在根据模式检查文档之前)预处理文档,Solr 为更新请求处理器提供了文档预处理插件,称为 更新请求处理器,这些插件允许使用默认和自定义配置链。

UpdateRequestHandler 配置

默认配置文件默认情况下配置了更新请求处理器。

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

XML 格式的索引更新

可以使用 Content-type: application/xmlContent-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 的复制机制在多个系统之间分发搜索,请注意,优化后,需要传输完整的索引。

您应该只考虑对静态索引使用优化,即可以在定期更新过程中(例如每天更新一次)优化的索引。需要 NRT 功能的应用程序不应使用优化。

<commit><optimize> 元素接受以下可选属性

waitSearcher

可选

默认值:true

阻塞,直到打开一个新的搜索器并将其注册为主查询搜索器,从而使更改可见。

expungeDeletes

可选

默认值:false

合并删除文档超过 10% 的段,在此过程中清除删除的文档。生成的段将遵守 maxMergedSegmentMB。此选项仅适用于 <commit> 操作。

expungeDeletes 比优化更便宜,但相同的警告适用。
maxSegments

可选

默认值:无

尽力尝试将段合并到不超过此数量的段,但不保证能实现目标。除非有确凿的证据表明优化到少量段是有益的,否则应省略此参数并接受默认行为。此选项仅适用于 <optimize 操作。默认值为无限制,生成的段将遵守 maxMergedSegmentMB 设置。

以下是使用可选属性的 <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>

在按查询删除中使用 Join 查询解析器时,应使用 score 参数,其值为“none”,以避免 ClassCastException。有关 score 参数的更多详细信息,请参阅有关 Join 查询解析器 的部分。

回滚操作

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

分组操作

您可以通过使用周围的 <update> 元素将它们分组,在一个 XML 文件中发布多个命令。

<update>
  <add>
    <doc><!-- doc 1 content --></doc>
  </add>
  <add>
    <doc><!-- doc 2 content --></doc>
  </add>
  <delete>
    <id>0002166313</id>
  </delete>
</update>

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

上述方法效果很好,但使用 --data-binary 选项会导致 curl 在将其发布到服务器之前将整个 myfile.xml 加载到内存中。在处理多吉字节文件时,这可能会有问题。此替代 curl 命令执行等效操作,但 curl 内存使用量最小

curl http://localhost:8983/solr/my_collection/update -H "Content-Type: text/xml" -T "myfile.xml" -X POST

如果在 solrconfig.xmlrequestParsers 元素中启用,则也可以使用 HTTP GET 命令发送简短请求,对请求进行 URL 编码,如下所示。请注意对“<”和“>”的转义

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

来自 Solr 的响应采用此处所示的形式

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

如果发生错误,状态字段将不为零。

使用 XSLT 转换 XML 索引更新

脚本模块 提供了一个单独的 XSLT 更新请求处理程序,允许您通过使用 <tr> 参数应用 XSL 转换 来索引任何任意 XML。您必须在 configsetconf/xslt 目录中有一个 XSLT 样式表,它可以将传入的数据转换为预期的 <add><doc/></add> 格式,并使用 tr 参数指定该样式表的名

在使用此功能之前,您需要启用 脚本模块

tr 参数

XSLT 更新请求处理程序接受 tr 参数,该参数标识要使用的 XML 转换。必须在 Solr conf/xslt 目录中找到转换。

XSLT 配置

以下示例来自 Solr 发行版中的 sample_techproducts_configs configset,展示了如何配置 XSLT 更新请求处理程序。

<!--
  Changes to XSLT transforms are taken into account
  every xsltCacheLifetimeSeconds at most.
-->
<requestHandler name="/update/xslt"
                     class="solr.scripting.xslt.XSLTUpdateRequestHandler">
  <int name="xsltCacheLifetimeSeconds">5</int>
</requestHandler>

xsltCacheLifetimeSeconds 的值为 5 对于开发来说很好,可以快速看到 XSLT 更改。对于生产环境,您可能需要一个更高的值。

XSLT 更新示例

以下是 sample_techproducts_configs/conf/xslt/updateXml.xsl XSL 文件,用于将标准 Solr XML 输出转换为 Solr 预期的 <add><doc/></add> 格式

<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 文件的格式中(前提是所有字段都被存储)

$ curl -o standard_solr_xml_format.xml "http://localhost:8983/solr/techproducts/select?q=ipod&fl=id,cat,name,popularity,price,score&wt=xml"

$ curl -X POST -H "Content-Type: text/xml" -d @standard_solr_xml_format.xml "http://localhost:8983/solr/techproducts/update/xslt?commit=true&tr=updateXml.xsl"
您可以在 响应编写器 XSLT 示例 中使用 tr 参数看到相反的导出/导入循环。

JSON 格式的索引更新

Solr 可以接受符合定义结构的 JSON,也可以接受任意格式的 JSON 文档。如果发送任意格式的 JSON,则需要使用更新请求发送一些额外的参数,这些参数在 转换和索引自定义 JSON 部分中描述。

Solr 风格的 JSON

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

JSON 格式的更新可以采用 3 种基本形式,下面将详细介绍

  • 单个文档,表示为顶级 JSON 对象。为了将其与一组命令区分开来,需要 json.command=false 请求参数。

  • 多个文档的列表,表示为顶级 JSON 数组,每个文档包含一个 JSON 对象。

  • 更新命令序列,表示为顶级 JSON 对象(映射)。

添加单个 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 数组一次添加多个文档,其中每个对象代表一个文档

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"
  }
]'

example/exampledocs/books.json 中提供了一个示例 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 更新语法支持 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 按查询删除

与其他更新处理程序一样,commitcommitWithinoptimizeoverwrite 等参数可以在 URL 中指定,而不是在消息正文中指定。

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

{ "delete":"myid" }

或文档 ID 列表

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

注意:按 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 格式的更新命令的客户端很有用,而 /update/json/docs 路径对于始终想要发送文档(单独或作为列表)而无需担心完整 JSON 命令语法的客户端来说特别方便。

自定义 JSON 文档

Solr 可以支持自定义 JSON。这在 转换和索引自定义 JSON 部分中介绍。

CSV 格式的索引更新

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

example/exampledocs/books.csv 中提供了一个示例 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

可选

默认值:false

如果为 true,则从值中删除前导和尾随空格。此参数可以是全局的,也可以是每个字段的。

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

header

可选

默认值:true

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

fieldnames

可选

默认值:无

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

示例:fieldnames=isbn,price,title

literal.field_name

可选

默认值:无

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

示例:literal.color=red

skip

可选

默认值:无

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

示例:skip=uninteresting,shoesize

skipLines

可选

默认值:0

在 CSV 数据开始之前要丢弃的输入流中的行数,包括标题(如果存在)。此参数是全局的。

示例:skipLines=5

encapsulator

可选

默认值:无

可选地用于包围值的字符,以保留诸如 CSV 分隔符或空格之类的字符。此标准 CSV 格式通过将封装器加倍来处理封装器本身出现在封装值中的情况。

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

示例:encapsulator="

escape

可选

默认值:无

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

示例:escape=\

keepEmpty

可选

默认值:false

保留和索引零长度(空)字段。此参数可以是全局的,也可以是每个字段的。

示例:f.price.keepEmpty=true

map

可选

默认值:无

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

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

split

可选

默认值:无

如果为 true,则通过单独的解析器将字段拆分为多个值。此参数用于每个字段,例如 f.FIELD_NAME_GOES_HERE.split=true

overwrite

可选

默认值:true

如果为 true,则根据 Solr 架构中声明的 uniqueKey 字段检查并覆盖重复文档。如果您知道要索引的文档不包含任何重复项,那么将此设置为 false 可以显着提高速度。

此参数是全局的。

commit

可选

默认值:无

在数据被摄取后发出提交。此参数是全局的。

commitWithin

可选

默认值:无

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

示例:commitWithin=10000

rowid

可选

默认值:无

rowid(行号)映射到参数值指定的字段,例如,如果您的 CSV 没有唯一键,并且您想使用行 ID 作为唯一键。此参数是全局的。

示例:rowid=id

rowidOffset

可选

默认值:0

在将 rowid 添加到文档之前,将给定的偏移量(作为整数)添加到 rowid。此参数是全局的。

示例:rowidOffset=10

索引制表符分隔文件

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

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

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

然后,可以通过将 separator 设置为制表符 (%09) 以及 escape 设置为反斜杠 (%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 证明很困难。