Solr无架构模式

2018-11-13 16:10 更新
无架构模式是一组 Solr 功能,它们一起使用时,用户只需简单地对示例数据进行索引就可以快速构建有效的架构,而无需手动编辑模式。

这些 Solr 功能都是通过 solrconfig.xml 方式控制的:

  1. 托管架构:在运行时通过 Solr API 进行架构修改,这需要使用支持这些更改的 schemaFactory。有关更多详细信息,请参阅 SolrConfig 中的 "架构工厂定义" 部分。
  2. 字段值类猜测:以前看不到的字段是通过一组级联的价值分析器来运行的,它们猜测 Java 类的字段值 - 布尔型、整数型、长整型、浮点型、双精度型和日期型的解析器当前可用。
  3. 基于字段值类(es)的自动模式字段添加:基于字段值 Java 类(字段值映射到架构字段类型),将先前看不到的字段添加到模式中。 - 请参阅 Solr 字段类型。

使用无架构示例

无架构模式的三个特性是在 Solr 分配的 _default 配置集中预先配置的。要使用这些配置启动 Solr 的示例实例,请运行以下命令:

bin/solr start -e schemaless

这将启动一个 Solr 的服务器,并自动创建一个集合(名为 “gettingstarted 只包含三个初始架构字段”):id、_version_ 和 _text_。

你可以使用 /schema/fields Schema API 来确认:curl http://localhost:8983/solr/gettingstarted/schema/fields 输出:

{
  "responseHeader":{
    "status":0,
    "QTime":1},
  "fields":[{
      "name":"_text_",
      "type":"text_general",
      "multiValued":true,
      "indexed":true,
      "stored":false},
    {
      "name":"_version_",
      "type":"long",
      "indexed":true,
      "stored":true},
    {
      "name":"id",
      "type":"string",
      "multiValued":false,
      "indexed":true,
      "required":true,
      "stored":true,
      "uniqueKey":true}]}

配置无看过模式

如上所述,有三种配置元素需要在无架构模式下使用 Solr。在 _defaultSolr 包含的配置集中,这些已经配置好了。但是,如果您想自己实现无架构,则应进行以下更改。

启用托管架构

如 SolrConfig 中的 Schema Factory Definition 一节所述,除非您的配置指定 ClassicIndexSchemaFactory 应该使用 Managed Schema 支持,否则默认情况下启用 Managed Schema 支持。

您可以通过添加显式 <schemaFactory/> (如下所示) 来配置 ManagedIndexSchemaFactory (并控制所使用的资源文件,或禁用将来的修改),请参阅 SolrConfig中的架构工厂定义以获取有关可用选项的更多详细信息。

<schemaFactory class="ManagedIndexSchemaFactory">
  <bool name="mutable">true</bool>
  <str name="managedSchemaResourceName">managed-schema</str>
</schemaFactory>

启用字段类猜测

在 Solr 中,UpdateRequestProcessorChain 定义了一系列插件,这些插件在索引之前或索引时应用于文档。

Solr 的无架构模式的字段猜测方面使用专门定义的允许 Solr 猜测字段类型的 UpdateRequestProcessorChain。您还可以定义要使用的默认字段类型类。

首先,您应该如下定义它(更新处理器工厂文档,请参阅下面的 javadoc 链接):

<updateProcessor class="solr.UUIDUpdateProcessorFactory" name="uuid"/>
  <updateProcessor class="solr.RemoveBlankFieldUpdateProcessorFactory" name="remove-blank"/>
  <updateProcessor class="solr.FieldNameMutatingUpdateProcessorFactory" name="field-name-mutating"> 【1】
    <str name="pattern">[^\w-\.]</str>
    <str name="replacement">_</str>
  </updateProcessor>
  <updateProcessor class="solr.ParseBooleanFieldUpdateProcessorFactory" name="parse-boolean"/> 【2】
  <updateProcessor class="solr.ParseLongFieldUpdateProcessorFactory" name="parse-long"/>
  <updateProcessor class="solr.ParseDoubleFieldUpdateProcessorFactory" name="parse-double"/>
  <updateProcessor class="solr.ParseDateFieldUpdateProcessorFactory" name="parse-date">
    <arr name="format">
      <str>yyyy-MM-dd'T'HH:mm:ss.SSSZ</str>
      <str>yyyy-MM-dd'T'HH:mm:ss,SSSZ</str>
      <str>yyyy-MM-dd'T'HH:mm:ss.SSS</str>
      <str>yyyy-MM-dd'T'HH:mm:ss,SSS</str>
      <str>yyyy-MM-dd'T'HH:mm:ssZ</str>
      <str>yyyy-MM-dd'T'HH:mm:ss</str>
      <str>yyyy-MM-dd'T'HH:mmZ</str>
      <str>yyyy-MM-dd'T'HH:mm</str>
      <str>yyyy-MM-dd HH:mm:ss.SSSZ</str>
      <str>yyyy-MM-dd HH:mm:ss,SSSZ</str>
      <str>yyyy-MM-dd HH:mm:ss.SSS</str>
      <str>yyyy-MM-dd HH:mm:ss,SSS</str>
      <str>yyyy-MM-dd HH:mm:ssZ</str>
      <str>yyyy-MM-dd HH:mm:ss</str>
      <str>yyyy-MM-dd HH:mmZ</str>
      <str>yyyy-MM-dd HH:mm</str>
      <str>yyyy-MM-dd</str>
    </arr>
  </updateProcessor>
  <updateProcessor class="solr.AddSchemaFieldsUpdateProcessorFactory" name="add-schema-fields"> 【3】
    <lst name="typeMapping">
      <str name="valueClass">java.lang.String</str> 【4】
      <str name="fieldType">text_general</str>
      <lst name="copyField"> 【5】
        <str name="dest">*_str</str>
        <int name="maxChars">256</int>
      </lst>
      <!-- Use as default mapping instead of defaultFieldType -->
      <bool name="default">true</bool>
    </lst>
    <lst name="typeMapping">
      <str name="valueClass">java.lang.Boolean</str>
      <str name="fieldType">booleans</str>
    </lst>
    <lst name="typeMapping">
      <str name="valueClass">java.util.Date</str>
      <str name="fieldType">pdates</str>
    </lst>
    <lst name="typeMapping">
      <str name="valueClass">java.lang.Long</str> 【6】
      <str name="valueClass">java.lang.Integer</str>
      <str name="fieldType">plongs</str>
    </lst>
    <lst name="typeMapping">
      <str name="valueClass">java.lang.Number</str>
      <str name="fieldType">pdoubles</str>
    </lst>
  </updateProcessor>

  <!-- The update.autoCreateFields property can be turned to false to disable schemaless mode -->
  <updateRequestProcessorChain name="add-unknown-fields-to-the-schema" default="${update.autoCreateFields:true}"
           processor="uuid,remove-blank,field-name-mutating,parse-boolean,parse-long,parse-double,parse-date,add-schema-fields"> 【7】
    <processor class="solr.LogUpdateProcessorFactory"/>
    <processor class="solr.DistributedUpdateProcessorFactory"/>
    <processor class="solr.RunUpdateProcessorFactory"/>
  </updateRequestProcessorChain>

这条链上定义了很多东西。我们来看看其中的一些:

  1. 首先,我们使用 FieldNameMutatingUpdateProcessorFactory 来小写所有字段名称。注意,这个和每个后续的<processor>元素包括一个name。这些名称将在本例末尾的最后一个链定义中使用。
  2. 接下来,我们添加几个更新请求处理器来解析不同的字段类型。注意 ParseDateFieldUpdateProcessorFactory 包括一长串可能的日期的形成,会被解析成有效的 Solr 日期。如果您有一个自定义的日期,您可以将它添加到这个列表中(参见下面的 Javadocs 链接以获得关于如何实现的信息)。
  3. 一旦字段被解析,我们定义将被分配给这些字段的字段类型。您可以修改任何你想要改变的东西。
  4. 在这个定义中,如果解析步骤决定一个字段中的传入数据是一个字符串,那么我们将把它放到 Solr 中的字段类型为 text_general 的字段中。这个字段类型默认允许Solr 在这个字段上查询。
  5. 在我们添加了 text_general 字段之后,我们还定义了一个复制字段规则,它将从新的 text_general 字段复制所有数据到带有 _str 相同名称的字段。这是由 Solr 的动态字段特性完成的。通过用这种方式将复制字段规则的目标定义为一个动态字段,您可以控制模式中使用的字段类型。默认选择允许 Solr 在这些字段上进行 facet、高亮显示和排序。
  6. 这是映射规则的另一个例子。在这种情况下,我们定义当字段LongInteger字段解析器中的任何一个识别出字段时,它们应该将它们的字段映射到 plongs 字段类型。
  7. 最后,我们添加一个称为插件列表的链定义。当我们定义这些插件时,它们都是由我们给它们的名字命名的。我们还可以向链中添加其他处理器,如下所示。注意,我们还为整个链提供了一个 name (“添加未知字段到模式”)。我们将在下一节中使用这个名字来指定我们的更新请求处理程序应该使用这个链定义。

此链定义将为要从相应的文本字段创建的字符串字段建立多个复制字段规则。如果您的数据导致您最终使用了大量的复制字段规则,则索引可能会明显减慢,并且索引大小将会更大。为了控制这些问题,建议您查看创建的复制字段规则,并删除不需要的 faceting、排序、突出显示等。

如果您对这个链中使用的类的更多的信息感兴趣,下面是上面提到的更新处理器工厂的 Javadocs 的链接:

设置默认的 UpdateRequestProcessorChain

一旦定义了 UpdateRequestProcessorChain,你必须指示你的 UpdateRequestHandlers 在处理索引更新时使用它(即添加、删除、替换文档)。

有两种方法可以做到这一点。上面显示的更新链有一个、default=true、属性,将用于任何更新处理程序。

另一种更明确的方法是使用 InitParams 来设置所有/update请求处理程序的默认值:

<initParams path="/update/**">
  <lst name="defaults">
    <str name="update.chain">add-unknown-fields-to-the-schema</str>
  </lst>
</initParams>
Tip:完成所有这些更改后,应重新启动 Solr 或重新加载内核。

禁用自动字段猜测

使用 update.autoCreateFields 属性可以禁用自动字段创建。要做到这一点,您可以使用 Config API 和命令,例如:

curl http://host:8983/solr/mycollection/config -d '{"set-user-property": {"update.autoCreateFields":"false"}}'

索引文件的例子

一旦启用了无架构模式(无论是手动配置模式还是使用 _defaultconfigset),包含未在架构中定义的字段的文档将使用自动添加到架构的猜测字段类型进行索引。

例如,添加一个 CSV 文档会导致未知的字段被添加,字段类型基于值:

curl "http://localhost:8983/solr/gettingstarted/update?commit=true" -H "Content-type:application/csv" -d '
id,Artist,Album,Released,Rating,FromDistributor,Sold
44C,Old Shews,Mead for Walking,1988-08-13,0.01,14,0'

输出指示成功:

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

架构中的字段(输出自:curl http://localhost:8983/solr/gettingstarted/schema/fields):

{
  "responseHeader":{
    "status":0,
    "QTime":2},
  "fields":[{
      "name":"Album",
      "type":"text_general"},
    {
      "name":"Artist",
      "type":"text_general"},
    {
      "name":"FromDistributor",
      "type":"plongs"},
    {
      "name":"Rating",
      "type":"pdoubles"},
    {
      "name":"Released",
      "type":"pdates"},
    {
      "name":"Sold",
      "type":"plongs"},
    {
      "name":"_root_", ...},
    {
      "name":"_text_", ...},
    {
      "name":"_version_", ...},
    {
      "name":"id", ...}
]}

另外字符串版本的文本字段被索引,使用 copyFields 到 *_str 动态字段:(输出:curl http://localhost:8983/solr/gettingstarted/schema/copyfields):

{
  "responseHeader":{
    "status":0,
    "QTime":0},
  "copyFields":[{
      "source":"Artist",
      "dest":"Artist_str",
      "maxChars":256},
    {
      "source":"Album",
      "dest":"Album_str",
      "maxChars":256}]}

您仍然可以显式:即使您希望对大多数字段使用无架构模式,您仍然可以使用架构 API 在索引使用它们的文档之前先用创建的类型先行创建一些字段。

在内部,架构 API 和架构更新处理器都使用相同的托管架构功能。

此外,如果不需要文本字段的 * _str 版本,则可以从自动生成的架构中删除 copyField 定义,并且由于现在定义了原始字段,因此不会重新添加。

一旦一个字段被添加到架构,其字段类型是固定的。因此,添加具有与先前猜测的字段类型冲突的字段值的文档将失败。例如,在添加上面的文档之后,“ Sold” 字段具有 fieldType plongs,但是下面的文档在该字段中具有非整数十进制值:
curl "http://localhost:8983/solr/gettingstarted/update?commit=true" -H "Content-type:application/csv" -d '
id,Description,Sold
19F,Cassettes by the pound,4.93'

此文档将失败,如以下输出所示:

<response>
  <lst name="responseHeader">
    <int name="status">400</int>
    <int name="QTime">7</int>
  </lst>
  <lst name="error">
    <str name="msg">ERROR: [doc=19F] Error adding field 'Sold'='4.93' msg=For input string: "4.93"</str>
    <int name="code">400</int>
  </lst>
</response>
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号