外部文件和进程

Solr 支持使用名为 ExternalFileFieldType 的字段类型将字段值存储在外部文件中。它还可以使用名为 PreAnalyzedFieldType 的字段类型来使用已经过分析的标记流。

ExternalFileField 类型

ExternalFileField 类型使得可以在 Solr 索引之外的文件中指定字段的值。对于这样的字段,该文件包含从键字段到字段值的映射。另一种考虑方式是,Solr 不是在索引文档时指定文档中的字段,而是在外部文件中查找此字段的值。

外部字段不可搜索。它们只能用于函数查询或显示。有关函数查询的更多信息,请参阅关于 函数查询 的部分。

在以下情况下,ExternalFileField 类型非常方便:您希望比更新其余文档更频繁地更新许多文档中的特定字段。例如,假设您已根据浏览次数实现了文档排名。您可能希望每天或每小时更新所有文档的排名,而文档的其余内容可能更新频率较低。如果没有 ExternalFileField,您需要更新每个文档才能更改排名。使用 ExternalFileField 效率更高,因为特定字段的所有文档值都存储在外部文件中,您可以根据需要频繁更新该文件。

模式 中,此字段类型的定义可能如下所示:

<fieldType name="entryRankFile" keyField="pkId" defVal="0" stored="false" indexed="false" class="solr.ExternalFileField"/>

keyField 属性定义将在外部文件中定义的键。它通常是索引的唯一键,但只要 keyField 可以用于识别索引中的文档,就不需要那么长。defVal 定义一个默认值,如果外部文件中没有特定文档的条目,将使用该默认值。

外部文件的格式

文件本身位于 Solr 的索引目录中,默认情况下为 $SOLR_HOME/data。该文件的名称应为 external_fieldnameexternal_fieldname.*。那么,对于上面的示例,该文件可以命名为 external_entryRankFileexternal_entryRankFile.txt

如果出现任何使用 .* 名称模式(例如 .txt)的文件,则将使用最后一个文件(按名称排序后),并且将删除以前的版本。此行为支持在无法覆盖文件的系统上实施(例如,在 Windows 上,如果文件正在使用中)。

该文件包含将键字段(在等号的左侧)映射到值(在右侧)的条目。以下是一些示例条目:

doc33=1.414
doc34=3.14159
doc40=42

此文件中列出的键不需要是唯一的。该文件不需要排序,但如果排序,Solr 将能够更快地执行查找。

重新加载外部文件

可以定义一个事件监听器,以便在重新加载搜索器或启动新搜索器时重新加载外部文件。有关详细信息,请参阅与查询相关的监听器部分,但 solrconfig.xml 中的示例定义可能如下所示

<listener event="newSearcher" class="org.apache.solr.schema.ExternalFileFieldReloader"/>
<listener event="firstSearcher" class="org.apache.solr.schema.ExternalFileFieldReloader"/>

PreAnalyzedField 类型

PreAnalyzedField 类型提供了一种将序列化的令牌流(可选地包含字段的独立存储值)发送到 Solr 的方法,并且可以在 Solr 中存储和索引此信息,而无需应用任何额外的文本处理。如果用户希望提交已由某些现有外部文本处理管道处理过的字段内容(例如,已分词、注释、词干提取、插入同义词等),同时使用 Lucene 的 TokenStream 提供的所有丰富属性(每个令牌属性),则此方法非常有用。

序列化格式可以通过 PreAnalyzedParser 接口的实现进行插拔。有两种开箱即用的实现

  • JsonPreAnalyzedParser:顾名思义,它解析使用 JSON 表示字段内容的内容。如果未以其他方式配置字段类型,则这是要使用的默认解析器。

  • SimplePreAnalyzedParser:使用简单的严格纯文本格式,在某些情况下,它可能比 JSON 更容易创建。

只有一个配置参数 parserImpl。此参数的值应为实现 PreAnalyzedParser 接口的类的完全限定类名。此参数的默认值为 org.apache.solr.schema.JsonPreAnalyzedParser

默认情况下,此类型字段的查询时分析器将与索引时分析器相同,后者需要序列化的预分析文本。您必须向您的 fieldType 添加查询类型分析器,以便对非预分析查询执行分析。在下面的示例中,索引时分析器需要默认的 JSON 序列化格式,而查询时分析器将采用 StandardTokenizer/LowerCaseFilter

<fieldType name="pre_with_query_analyzer" class="solr.PreAnalyzedField">
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

JsonPreAnalyzedParser

这是 PreAnalyzedField 类型使用的默认序列化格式。它使用带有以下键的顶级 JSON 映射

描述 必需

v

版本键。当前支持的版本为 1

必需

str

字段的存储字符串值。您最多可以使用 strbin 中的一个。

可选

bin

字段的存储二进制值。二进制值必须经过 Base64 编码。

可选

tokens

序列化令牌流。这是一个 JSON 列表。

可选

任何其他顶级键都会被静默忽略。

令牌流序列化

令牌流表示为 JSON 映射的 JSON 列表。每个令牌的映射由以下键和值组成

描述 Lucene 属性 必需?

t

令牌

CharTermAttribute

表示当前令牌的 UTF-8 字符串

必需

s

起始偏移量

OffsetAttribute

非负整数

可选

e

结束偏移量

OffsetAttribute

非负整数

可选

i

位置增量

PositionIncrementAttribute

非负整数 - 默认为 1

可选

p

有效负载

PayloadAttribute

Base64 编码的有效负载

可选

y

词法类型

TypeAttribute

UTF-8 字符串

可选

f

标志

FlagsAttribute

表示十六进制格式整数值的字符串

可选

任何其他键都会被静默忽略。

JsonPreAnalyzedParser 示例

{
  "v":"1",
  "str":"test ąćęłńóśźż",
  "tokens": [
    {"t":"two","s":5,"e":8,"i":1,"y":"word"},
    {"t":"three","s":20,"e":22,"i":1,"y":"foobar"},
    {"t":"one","s":123,"e":128,"i":22,"p":"DQ4KDQsODg8=","y":"word"}
  ]
}

SimplePreAnalyzedParser

通过 parserImpl 配置参数指定此格式时要使用的完全限定类名为 org.apache.solr.schema.SimplePreAnalyzedParser

SimplePreAnalyzedParser 语法

此解析器支持的序列化格式如下

序列化格式
content ::= version (stored)? tokens
version ::= digit+ " "
; stored field value - any "=" inside must be escaped!
stored ::= "=" text "="
tokens ::= (token ((" ") + token)*)*
token ::= text ("," attrib)*
attrib ::= name '=' value
name ::= text
value ::= text

"text" 值中的特殊字符可以使用转义字符 \ 进行转义。以下转义序列被识别

转义序列 描述

\

字面空格字符

\,

字面 , 字符

\=

字面 = 字符

\\

字面 \ 字符

\n

换行符

\r

回车符

\t

水平制表符

请注意,不支持 Unicode 序列(例如,\u0001)。

支持的属性

支持以下令牌属性,并使用短符号名称标识

名称 描述 Lucene 属性 值格式

i

位置增量

PositionIncrementAttribute

整数

s

起始偏移量

OffsetAttribute

整数

e

结束偏移量

OffsetAttribute

整数

y

词法类型

TypeAttribute

字符串

f

标志

FlagsAttribute

十六进制整数

p

有效负载

PayloadAttribute

十六进制格式的字节;空格将被忽略

令牌位置被跟踪并隐式添加到令牌流中 - 开始和结束偏移量仅考虑术语文本和空格,而不包括令牌属性占用的空间。

示例令牌流

1 one two three
  • 版本:1

  • 存储:null

  • 令牌:(term=one,startOffset=0,endOffset=3)

  • 令牌:(term=two,startOffset=4,endOffset=7)

  • 令牌:(term=three,startOffset=8,endOffset=13)

1 one  two    three
  • 版本:1

  • 存储:null

  • 令牌:(term=one,startOffset=0,endOffset=3)

  • 令牌:(term=two,startOffset=5,endOffset=8)

  • 令牌:(term=three,startOffset=11,endOffset=16)

1 one,s=123,e=128,i=22 two three,s=20,e=22
  • 版本:1

  • 存储:null

  • 令牌:(term=one,positionIncrement=22,startOffset=123,endOffset=128)

  • 令牌:(term=two,positionIncrement=1,startOffset=5,endOffset=8)

  • 令牌:(term=three,positionIncrement=1,startOffset=20,endOffset=22)

1 \ one\ \,,i=22,a=\, two\=

\n,\ =\ \
  • 版本:1

  • 存储:null

  • 令牌:(term=one ,,positionIncrement=22,startOffset=0,endOffset=6)

  • 令牌:(term=two= ,positionIncrement=1,startOffset=7,endOffset=15)

  • 令牌:(term=\,positionIncrement=1,startOffset=17,endOffset=18)

请注意,未知的属性及其值将被忽略,因此在此示例中,第一个令牌上的“a”属性和第二个令牌上的“ ”(转义空格)属性及其值将被忽略,因为它们不属于支持的属性名称。

1 ,i=22 ,i=33,s=2,e=20 ,
  • 版本:1

  • 存储:null

  • 令牌:(term=,positionIncrement=22,startOffset=0,endOffset=0)

  • 令牌:(term=,positionIncrement=33,startOffset=2,endOffset=20)

  • 令牌:(term=,positionIncrement=1,startOffset=2,endOffset=2)

1 =This is the stored part with \=
\n \t escapes.=one two three
  • 版本:1

  • 存储:This is the stored part with = \t escapes.

  • 令牌:(term=one,startOffset=0,endOffset=3)

  • 令牌:(term=two,startOffset=4,endOffset=7)

  • 令牌:(term=three,startOffset=8,endOffset=13)

请注意,上面的存储值中的 \t 不是字面量;它以这种方式显示是为了直观地指示存储值中的实际制表符。

1 ==
  • 版本:1

  • 存储:""

  • (没有令牌)

1 =this is a test.=
  • 版本:1

  • 存储:this is a test.

  • (没有令牌)