Solr入门指南

Solr是一款独立的企业级搜索服务器,本指南将从Solr的安装、数据导入、查询入手,了解Solr中常见的概念。

Solr应用场景由最初的内容搜索,延伸到现今的电商产品查询、历史数据查询、地理空间搜索等各类应用场景中。

Solr有类似REST风格的API。

通过JSON、XML、CSV、HTTP文件,将文档放入Solr(称为“索引”)。

通过HTTP GET请求查询它,以JSON、XML、CSV或二进制方式返回结果。

Solr基于Lucene,并对Lucene做了扩展。

安装与启动

下载Solr,解压运行:

cd solr-x.x.x/bin

solr start -e cloud

SolrCloud模式启动Solr,询问启用多少个节点,默认2个,直接enter(回车)即可。

询问端口号,默认8983|7574(启用了两个节点)。

如果被占用可以调整,否则直接回车即可。

接着会提示创建用于索引数据的集合:

Now let's create a new collection for indexing documents in your 2-node cluster.
Please provide a name for your new collection: [gettingstarted]

输入一个字符串做名称,如:techproducts(后面查询时会用到)。

一路回车,直到看见:

SolrCloud example running, please visit: http://localhost:8983/solr

Solr启动成功。

添加索引

创建集合:

bin/solr create -c <yourCollection> -s 2 -rf 2

如:

bin/solr create -c films -s 2 -rf 2

命令使用默认的configSet(_default),configSet附带两个默认选项:

托管模式和字段猜测。

托管模式(Managed Schema)

该模式可使用Solr的Schema API对Schema执行修改,Schema存储与字段、字段类型的信息。

字段猜测(Schemaless Mode)

字段猜测无需在索引前定义文档(document)的所有字段。

能快速启动Solr,在有文档(document)时创建字段。

功能听起来很棒,实际上Solr不推荐用于生产环境。

一旦猜错,对拥有数百万个文档的数据集,重建索引会是个糟糕的过程,如果,此时已没有了原数据,重建就无从说起。

无模式功能(Schemaless Mode)对学习Solr是一个很好的开始,但不要对它有太多期望。

更多Solr脚本参见Solr控制脚本说明

创建字段

Solr示例数据中有一个films目录(solr\example\films),其中一个.csv的文件包含很多关于电影的信息。

文件的第一行中包含一部名为.45的电影,如果,使用solr数据猜测功能,将被认为是浮点类型的字段,那么,会导致后面的数据创建索引失败。

所以,创建索引前,在solr中设置“name”字段。

curl -X POST -H 'Content-type:application/json' --data-binary '{"add-field": {"name":"name", "type":"text_general", "multiValued":false, "stored":true}}' http://localhost:8983/solr/films/schema

Windows系统可借助postman之类的工具发送http请求。

也可通过solr管理界面创建字段,它降低了对字段属性的控制粒度。

solr add field

注:路径中的films参数,与实际的solr集合名称对应。

复制字段catchall

开始创建索引前还需做一个改动。

我们希望查询时不用指定字段,而是全字段匹配。

所以,将字段复制到一个text字段中,并在没有指定字段时,该字段为默认的查询字段。

定义一个复制字段(catchall):

curl -X POST -H 'Content-type:application/json' --data-binary '{"add-copy-field" : {"source":"*","dest":"_text_"}}' http://localhost:8983/solr/films/schema

在管理界面中,选择[添加复制字段],然后,填写字段来源和目标,如下图所示:

solr add copy field

这样就能把所有字段数据复制到“_text_”字段中。

添加索引数据

将位于example/films目录下的电影数据添加到索引。

它有三种格式:JSON、XML、CSV。

选择其中一种,将其索引到“films”集合:

Linux/Mac

JSON格式

bin/post -c films example/films/films.json

XML格式

bin/post -c films example/films/films.xml

CSV格式

bin/post -c films example/films/films.csv -params "f.genre.split=true&f.directed_by.split=true&f.genre.separator=|&f.directed_by.separator=|"

Windows

JSON格式

C:\solr> java -jar -Dc=films -Dauto example\exampledocs\post.jar example\films\*.json

XML格式

C:\solr> java -jar -Dc=films -Dauto example\exampledocs\post.jar example\films\*.xml

CSV格式

C:\solr-7.7.0> java -jar -Dc=films -Dparams=f.genre.split=true&f.directed_by.split=true&f.genre.separator=|&f.directed_by.separator=| -Dauto example\exampledocs\post.jar example\films\*.csv

CSV命令包含的额外参数,确保“genre”和“directed_by”列中由(|)字符分隔的多个条目,能被Solr正确索引。

注:-Dc参数与实际的solr集合名称对应。

查看索引数据

http://localhost:8983/solr/#/<yourCollection> /query

如:

http://localhost:8983/solr/#/films/query

在构建数据集合时,如果使用了其他名称,访问路径中的名称就要做相应调整。

直接点击[Execute Query]按钮,查询数据。

在q标签下方的输入框中填入:.45,替换掉默认的(*:*),能够看出查询结果发生了变化。

再尝试输入directed_by:Gary Lennon。

如果,希望使用短语搜索,需借助双引号,如:q="multiple terms here"

更多查询方法参见Solr示例数据

索引工具

bin/post

Solr命令行工具。

./bin/post -c localDocs ~/Documents

DataImportHandler

DataImportHandler(DIH)工具,能连接到数据库(需jdbc驱动),邮件服务器及其他结构化数据源。

https://lucene.apache.org/solr/guide/7_7/uploading-structured-data-store-data-with-the-data-import-handler.html#uploading-structured-data-store-data-with-the-data-import-handler

SolrJ

SolrJ是一款基于Java的solr客户端,能与Solr交互。

SolrJ用于JVM语言,以编程方式创建要发送的Solr文档。

Documents Screen

使用Admin UI Documents选项卡(位于http://localhost:8983/solr/#/localDocs/documents)粘贴要添加索引的文档。

或者从文档类型下拉列表中选择document Builder,一次构建一个文档。

单击表单下方的Submit Document按钮索引文档。

数据处理

Solr数据模式能在有与无之间自由切换。

Solr Schemaless模式(模式猜测)便于入门,配置模式用于构建稳定的生产环境。

动态字段的特性方便动态添加新字段,solr能通过外部配置文件,声明禁用词列表,同义词列表和受保护词列表。

以扩展的方式,支持应用专有格式和原本不支持的数据类型。

Solr document

文档是solr最基本的信息单元,是一组描述内容的数据。

如,关于食谱的document会包含:成分、说明、烹饪时长、所需工具等。

关于人的document可能会包含:姓名、传记、喜欢的颜色、鞋码。

关于书籍的文档可能包含:标题、作者、出版年份、页数等。

Solr中document由字段组成,字段拥有更具体的信息,如:名字、姓氏、鞋子大小。

字段能包含不同类型的数据,如:文本、浮点数。

字段类型告诉solr如何解析字段,以及如何查询字段。正确定义字段类型,有助于用户在执行查询时得到更好的结果。

添加文档时,solr会获取文档字段中的信息,将该信息添加到索引中。

执行查询时,solr通过查询索引返回匹配的文档。

Solr Schema File

Solr schema用于告诉solr,如何对document执行索引构建。

Solr Schema文件中存储着字段类型和字段定义信息。

文件的名称和位置与Solr的配置有关。

managed-schema是它的名称。

通过solrconfig.xml文件中的<schemaFactory/>节点进行修改:

Solr Schema分为托管模式(Managed Schema)和经典配置(schema.xml)两种。

Solr6.0后默认使用托管模式,该模式支持Schema API处理Schema数据,灵活性更高。

Managed Schema:

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

Classic schema.xml:

<schemaFactory class="ClassicIndexSchemaFactory"/>

如需修改Schema文件的默认名称,通过显式配置ManagedIndexSchemaFactory,将mutable选项设为true(false用于“锁定”修改)。

managedSchemaResourceName为可选参数,是Schema文件名称,默认值“managed-schema”,该值可以是“schema.xml”以外的任何名称。

schema.xml是Schema文件的传统名称。

如果,使用的是SolrCloud,本地文件系统中可能找不到这类文件。 两种模式间的切换,参见solr classic schema

有关修改Solr Schema定义参见schema factory definition in solrconfig

Schemaless Mode

Schemaless Mode是一组Solr功能,它们一起使用时,允许用户通过简单地索引样本数据,快速构建有效的schema,无需手动编辑schema。

Solr的Schemaless Mode使用时需具备三个条件:

托管模式(Managed schema)、字段猜测(Field value class guessing)、(自动添加字段)Automatic schema field addition, based on field value class。

Schemaless Mode三个选项的设置参见:solr using the schemaless example

定义字段类型

通过字段对应的索引查询文档时,solr会分析字段的类型。

字段类型在schema.xml中定义,通过fieldType元素定义具体类型。

Solr内置很多字段类型,提供货币日期枚举的处理,以及外部文件处理(Solr ExternalFileField Type),Solr ExternalFileField Type常用于临时提高某些document排名。

<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100"> 
  <analyzer type="index"> 
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
    <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>

示例中的第一行包含名称为text_general,类型为solr.TextField的字段。

其余部分是关于字段分析时(Field Analysis)要用到的。

schema.xml文件中,solr.是org.apache.solr.schema.或org.apache.solr.analysis.的缩写。

所以,solr.TextField代表org.apache.solr.schema.TextField类,字段的实现类(solr.TextField)负责确保字段被正确处理。

具体细节参见Solr field type definitions and properties

Solr 定义字段

Solr中字段通过schema.xml文件中的field元素定义,前面已了解如何定义字段类型,定义字段就相对简单很多。

<field name="price" type="float" default="0.0" indexed="true" stored="true"/>

示例中定义了一个名为price的字段,类型为float,默认值为0.0。

索引和存储属性被显式地设置为true,针对float类型所做的属性设置都将被继承到此。

field属性说明

name

字段名称,每个字段都必须有一个名称。

字段名称仅包含字母数字或下划线字符,不能以数字开头。

目前尚未严格执行此操作,但无法保证后向兼容性。

包含前导和尾部下划线的名称(如,_version_)目前保留。

type

字段类型,其值来源于fieldType定义。

每个字段必须有一个type。

default

默认值,在索引时如果文档的此字段没有值则使用默认值。

更多属性参见Solr optional field type override properties

Solr Copying Fields

如果,希望sorl以多种方式解释某些文档的字段。

可使用solr的Copying Fields,这种复制字段机制,能将几种不同的字段类型作为一个输入。

<copyField source="cat" dest="text" maxChars="30000" />

示例中,solr将cat字段复制到名为text的字段中。

意味着两个具有相同内容的字段,能使用不同的分析链以不同的方式存储在索引中。

该功能一个常见用法是创建单个“搜索”字段,当用户或客户端未指定查询字段时,将该字段作为默认查询字段。

<copyField source="*_t" dest="text" maxChars="25000" />

如title、author、keywords、body都应该是默认搜索字段,可以将这些字段复制到一个catchall的字段中,将catchall作为默认查询字段。

需要注意的是复制发生在source级别,不能把一个副本作为另一个副本的源,以下为错误示范:

<copyField source="here" dest="there"/>
<copyField source="there" dest="elsewhere"/>

更多细节参见:Solr copying fields

Solr动态字段(Dynamic Fields)

Solr动态字段允许solr在索引时使用没有明确定义的字段。

如果忘记定义字段,solr这一特性提供了一定灵活性,保证应用程序不那么脆弱。

动态字段和常规字段一样,除了名称中带有通配符。

在solr索引文档时,当一个字段没匹配到显式定义的字段,都可与动态字段尝试匹配。

<dynamicField name="*_i" type="int" indexed="true"  stored="true"/>

如,schema中包含名称为*_i的动态字段。

如果,尝试使用cost_i字段索引文档,但cost_i未在schema中显式定义,则cost_i字段将与*_i进行匹配。

Solr Schema API

Schema API是一种通过HTTP REST接口管理schema元素的方式。

API提供对Solr Schema读写访问权限。

支持进行字段和字段类型进行添加、删除、替换等操作。


-curl -X POST -H 'Content-type:application/json' --data-binary '{
  "add-field":{
     "name":"sell_by",
     "type":"pdate",
     "stored":true }
}' http://localhost:8983/api/cores/gettingstarted/schema

更详细示例参见:Solr schema api

属性分析(Field Analysis)

Field analysis告诉solr如何对传入的数据进行索引构建,这个过程的更准确的叫法可能是处理(processing)或者消化(digestion),但solr官方称之为分析(analysis)。

一个关于人的文档中,其中一个字段用于存放人物的传记,传记中每个词都必须编入索引,以便能通过查询传记中相关信息快速找到此人。

然而,传记中可能包含许多平时生活中不会关心的词,如"the"、"a"、"to"等等。

又或者希望查询时大小写不敏感。

这些问题的解决方案都需要依赖Field Analysis。

Solr在处理文本数据时,涉及到三个主要概念:分析器、标记器、过滤器。

字段分析器(Field analyzers )

字段分析器(Field analyzers )在文档被索引和查询时使用,分析器检查字段的文本并生成令牌流。

分析器可以是单个类,也可以由一系列标记器和过滤器类构成。

分析器通过schema.xml文件中<fieldType>子元素配置。

正常使用中,只有类型为“solr.TextField或solr.SortableTextField的字段才指定分析器。

配置分析器最简单的方法是使用一个analyzer元素,该元素的class属性是一个完全限定的java类。

此类必须是Analyzer类的子类

org.apache.lucene.analysis.Analyzer

如:

<fieldType name="nametext" class="solr.TextField">
  <analyzer class="org.apache.lucene.analysis.core.WhitespaceAnalyzer"/>
</fieldType>

注:此处solr.是org.apache.solr.的缩写。

即使最复杂的analysis需求,通常也可以被分解为一系列离散的、相对简单的处理步骤。

Solr发行版附带大量的标记器和过滤器,涵盖大多数可能遇到的场景。

建立分析仪链非常简单,指定一个<analyzer>元素(没有class属性),其子元素按照希望的顺序安排分词器和过滤器工厂。

<fieldType name="nametext" class="solr.TextField">
  <analyzer>
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.StopFilterFactory"/>
    <filter class="solr.EnglishPorterFilterFactory"/>
  </analyzer>
</fieldType>

更多细节参见solr analyzers

分词器(Tokenizers)

分词器(Tokenizers)将字段数据分解为词法单元或令牌。

<fieldType name="text" class="solr.TextField">
  <analyzer>
    <tokenizer class="solr.StandardTokenizerFactory"/>
  </analyzer>
</fieldType>

tokenizer元素中指定的类不是实际的tokenizer,而是实现了TokenizerFactory的类。

通过调用工厂类,根据需要创建tokenizer实例。

工厂创建的对象必须是Tokenizer的子类。

更多细节参见solr tokenizers

过滤器(Filters)检查令牌流以决定是否保留、转换、丢弃、创建新的令牌。

标记器和过滤器可以组合成管道或链,前一个输出作为下一个的输入。

这样的标记器和过滤器序列称为分析器,分析器的输出结果用于匹配查询结果或构建索引。

<fieldType name="text" class="solr.TextField">
  <analyzer>
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.EnglishPorterFilterFactory"/>
  </analyzer>
</fieldType>

更多细节参见solr filters

索引(Solr Indexing)

Solr索引接受来自不同来源的数据,包括XML、CSV、数据库及常用的文件格式(如Microsoft Word或PDF)。

Solr添加索引的三种最常用方法:

Solr Cell框架提取文件、HTTP请求上传XML文件、Solr Java API提取数据。

无论使用哪种数据提取方式,都有一个通用的基础数据结构,将数据输入solr索引:

包含多个字段的文档(document),每个字段都有名称和内容,这些字段可能是空的。

通常有一个惟一ID字段(类似于数据库中的主键),尽管solr并不严格要求使用惟一ID字段。

Solr Cell

Apache Tika是一款内容检测、分析的工具包,能从上千种不同的文件类型(如PPT,XLS和PDF)中检测提取元数据和文本。

Solr利用Tika项目构建了一个框架(Solr Cell),将许多不同文件格式的解析器(如Apache PDFBoxApache POI)集成到solr中。

Solr Cell默认不包含在solr中,所以,需要进行配置。

如果使用solr的示例配置项,默认是配置了Solr Cell的。

Solr附带了两个示例配置集(server/solr/configsets),配置集的名称为_default和sample_techproducts_configs。

如果对这些配置没什么兴趣,可尝试solr schemaless模式,包含Tika框架示例配置集。

bin/solr -e techproducts

启动solr后,可发送HTTP POST发送,操作solr附带的示例PDF文件:

curl 'http://localhost:8983/solr/techproducts/update/extract?literal.id=doc1&commit=true' -F "myfile=@example/exampledocs/solr-word.pdf"

说明:通过URL调用ExtractingRequestHandler,上传一个solr-word.pdf文件,并分配一个ID:doc1。

使用commit=true要求SOLR执行索引文件提交后,能够立即搜索到。

如果批量加载很多文档,为获取最佳性能,在完成前不要调用commit命令。

-F标志是curl POST请求上传上文件(multipart/form-data)时的参数。

@符号标示上传附件。

参数myfile=@example/exampledocs/solr-word.pdf为上传文件。

手动配置Solr Cell

如果未使用示例配置集,需要手动配置以加载Solr Cell所需的jar包。

在solrconfig.xml中查找ExtractingRequestHandler及依赖项:

<lib dir="${solr.install.dir:../../..}/contrib/extraction/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../..}/dist/" regex="solr-cell-\d.*\.jar" />

然后,在solrconfig.xml中配置ExtractingRequestHandler。

Solr的_default configset中可找到默认配置,根据需要修改:

<requestHandler name="/update/extract"
                startup="lazy"
                class="solr.extraction.ExtractingRequestHandler" >
  <lst name="defaults">
    <str name="lowernames">true</str>
    <str name="fmap.content">_text_</str>
  </lst>
</requestHandler>

使用Solr Cell框架时,记住以下几点:

Tika将自动尝试判断文档类型(如:Word、PDF、HTML)并提取内容。

使用stream.type参数为Tika显式指定MIME类型。

有关支持的文件类型,参见Tika formats

Tika内部工作原理简单地说就是,将已解析文档的内容合成XHTML文档,传递给Solr Cell的SAX ContentHandler。

Solr响应Tika的SAX事件,从提取的内容中创建一个或多个文本字段。

Tika根据DublinCore(元数据规范)等规范生成标题、主题、作者等元数据。

可用的元数据高度依赖于文件类型及所包含的内容。

Solr Cell将内部XHTML中的文本连接到内容字段。

可配置哪些元素应被包含哪些该被忽略,及哪些元素需要映射到另一个字段。

Solr Cell默认将每个元数据块映射到同名字段,可以通过参数控制修改。

当Solr Cell在内部完成SolrInputDocument创建后,Solr索引创建程序将接管。

更多细节配置参见Solr Cell configuring