想法占位

Solr cache sizes should be tuned to the number of documents in the
index, the queries, and the number of results you usually get from Solr.
我想,我应该做一个自动调整缓存的功能。先占个位,等全面了解完 solr 后再行实行。

Solr自带分词器,过滤器,语言分析

占位

接下来本来应该讲解 Solr 自带的分词器、过滤器和语言分析,鉴于这一部分内容多而繁琐,很多在中文处理中用不到,暂时先略过,以后有时间补上。

分词器

文本字段的分词器配置在 schema.xml 中的 <analyzer> 元素下的:

<br />
&lt;fieldType name=&quot;text&quot; class=&quot;solr.TextField&quot;&gt;<br />
	&lt;analyzer type=&quot;index&quot;&gt;<br />
		&lt;tokenizer class=&quot;solr.StandardTokenizerFactory&quot; /&gt;<br />
		&lt;filter class=&quot;solr.StandardFilterFactory&quot; /&gt;<br />
	&lt;/analyzer&gt;<br />
&lt;/fieldType&gt;<br />

这个class属性指明一个工厂类,这个工厂类在需要的时候可以产生一个分词器的实例。分词器工厂类实现了 org.apache.solr.analysis.TokenizerFactory ,TokenizerFactory 的 create 方法接受一个 reader 然后返回一个 TokenStream。当 solr 创建了分词器,通过一个 reader 传递文本的字段内容给分词器。

可以通过设置 <tokenizer> 元素的属性给分词器传递参数。
<br />
&lt;fieldType name=&quot;semicolonDelimited&quot; class=&quot;solr.TextField&quot;&gt;<br />
	&lt;analyzer type=&quot;query&quot;&gt;<br />
		&lt;tokenizer class=&quot;solr.PatternTokenizerFactory&quot; pattern=&quot;; &quot; /&gt;<br />
		&lt;analyzer&gt;<br />
&lt;/fieldType&gt;<br />

什么是过滤器

和切词器一样,过滤器也是消费输入,然后输出一串的 tokens,过滤器也是继承自 org.apache.lucene.analysis.TokenStream。和切词器不一样的是,一个过滤器的输入是另一种TokenStream。通常情况下,过滤器的工作比切词器简单,过滤器拿着每个token,决定是继续流转下去或者替换或者抛弃。
过滤器消费一个 TokenStream 然后产生一个新的 TokenStream,过滤器可以一个接一个组成一个链。链上的每个过滤器按顺序执行,因此注明过滤器的顺序显得很重要。通常情况下,先执行普通过滤器,然后执行专业过滤器。
&lt;fieldType name=&quot;text&quot; class=&quot;solr.TextField&quot;&gt;<br />
&lt;analyzer&gt;<br />
&lt;tokenizer class=&quot;solr.StandardTokenizerFactory&quot;/&gt;<br />
&lt;filter class=&quot;solr.StandardFilterFactory&quot;/&gt;<br />
&lt;filter class=&quot;solr.LowerCaseFilterFactory&quot;/&gt;<br />
&lt;filter class=&quot;solr.EnglishPorterFilterFactory&quot;/&gt;<br />
&lt;/analyzer&gt;<br />
&lt;/fieldType&gt;

这个例子以solr标准分词器为开始,这个分词器会将字段的文本拆分成tokens,这些tokens再通过solr标准过滤器,标准过滤器移除字母中的点号,并且执行一些其他通用的操作。然后所有的token被转成小写,这样查询时可以匹配大小写不敏感搜索。
上面例子中最后一个过滤器是一个 stemmer 过滤器,它使用了Porter算法。

什么是分词器

分词器的工作是将一串的文本切成 tokens,这些 token 一般是文本的子集。分析器的处理对象时一个字段,分词器则是面对一串文本,分词器读取一串文本,然后将其切割成一堆的 token 对象。
字符串中的空格或连接符会被删除。字符将被添加或者替换,如映射别名,或者缩写替换缩写为正常格式。分词器可能会产生出与原字段值不一致的token,或者长度与原始文本不一致。这个在token元数据用于文本字段高亮搜索结果时需要注意。
<br />
&lt;fieldType name=&quot;text&quot; class=&quot;solr.TextField&quot;&gt;<br />
&lt;analyzer&gt;<br />
&lt;tokenizer class=&quot;solr.StandardTokenizerFactory&quot;/&gt;<br />
&lt;/analyzer&gt;<br />
&lt;/fieldType&gt;<br />

<tokenizer>元素的类名称不是一个真实的分词器,但是它指向一个实现了org.apache.solr.analysis.TokenizerFactory接口的类。这个工厂在需要的时候会创建一个分词器的实例。工厂创建出来的对象必须继承 org.apache.lucene.analysis.TokenStream.
(这篇翻译的比较烂,对分词这块了解不够深刻,有空再回来修订)

分析阶段

在两个时间需要用到分析。在索引时,当一个字段被创建时,分析这个字段得到的 token stream 将被加入索引库,并且定义出这个字段的 terms(包括位置、大小等等)。在查询时,搜索词将被分析,并且去字段的索引中匹配相应的 terms。

在许多情况下,同样的分析会被应用在两个阶段,比如精准搜索,需要索引和搜索时采用同样的分析策略。在其他情况下,索引和搜索所采用的策略会有所不同。
如果字段类型只是简单定义了 <analyzer> ,这样相同的分析策略会被应用到索引和搜索阶段。如果打算搜索和索引采用不同的分析策略,字段类型定义中需要包含两个 <analyzer> ,如下所示:
<br />
&lt;fieldType name=&quot;nametext&quot;&gt;<br />
&lt;analyzer *type=&quot;index&quot;{*}&gt;<br />
&lt;tokenizer/&gt;<br />
&lt;filter/&gt;<br />
&lt;filter words=&quot;keepwords.txt&quot;/&gt;<br />
&lt;filter synonyms=&quot;syns.txt&quot;/&gt;<br />
&lt;/analyzer&gt;<br />
&lt;analyzer *type=&quot;query&quot;{*}&gt;<br />
&lt;tokenizer/&gt;<br />
&lt;filter/&gt;<br />
&lt;/analyzer&gt;<br />
&lt;/fieldType&gt;<br />

在上面例子中,在索引时,文本内容将被转成小写,不存在keepwords.txt中的文本将被丢弃,剩下的将被替换syns.txt中的同义词。
在搜索时,会将搜索词转成小写,索引阶段的过滤和映射步骤搜索时没有定义,就不会发生。

什么是分析器(Analyzer)

一个分析器可以检查字段的文本信息,并且产生一个 token 流。分析器是 schema.xml 中的 <fieldType> 元素的一个子元素,schema.xml 可以在 solr/conf 目录下找到或者跟 solrconfig.xml 在同一目录。
通常使用中,只有 solr.TextField 类型的字段会专门制定一个分析器。最简单配置一个分析器的方式是使用 <analyzer> 元素,制定这个元素的 class 属性为一个完整的 Java 类名。这些类名必须源自 org.apache.lucene.analysis.Analyzer 。以下是个例子:
<br />
&lt;fieldType name=&quot;nametext&quot; class=&quot;solr.TextField&quot;&gt;<br />
&lt;analyzer class=&quot;org.apache.lucene.analysis.WhitespaceAnalyzer&quot;/&gt;<br />
&lt;/fieldType&gt;<br />

在这个例子中,WhitespaceAnalyzer 这个类负责分析文本字段的内容并且产生出正确的 tokens。举个简单例子,简明英文散文,像这样的一个分析器的类足可以应付了。但是经常需要对字段内容做复杂的分析。
复杂的分析,需要分析成多个独立的简单步骤进行处理。比较直截了当的方式是设置分析器的链。指定一个简单的 <analyzer> 元素(不是类属性),该元素带有用做分析器和过滤器的工厂类。示例:
<br />
&lt;fieldType name=&quot;nametext&quot; class=&quot;solr.TextField&quot;&gt;<br />
&lt;analyzer&gt;<br />
&lt;tokenizer class=&quot;solr.StandardTokenizerFactory&quot;/&gt;<br />
&lt;filter class=&quot;solr.StandardFilterFactory&quot;/&gt;<br />
&lt;filter class=&quot;solr.LowerCaseFilterFactory&quot;/&gt;<br />
&lt;filter class=&quot;solr.StopFilterFactory&quot;/&gt;<br />
&lt;filter class=&quot;solr.EnglishPorterFilterFactory&quot;/&gt;<br />
&lt;/analyzer&gt;<br />
&lt;/fieldType&gt;<br />

需要说明的话solr.前缀的包,其实是指向 org.apache.solr.analysis 这个包。
在这个例子中,在 <analyzer> 元素没有指定分析器的类,而是一系列的类共同承担一个字段的分析器。字段的文本首先传到列表的第一个元素(solr.StandardTokenizerFactory),然后在最后一个元素(solr.EnglishPorterFilterFactory)产生出 tokens,这些 tokens 作为 terms 在字段的索引和查询时使用。

选择正确的数字类型

一般情况下,可使用可排序的数字类型,如SortableIntField, SortableLongField,
SortableFloatField 和 SortableDoubleField。在排序方便,这些可排序的数字类型会比 IntField, LongField, FloatField 和 DoubleField 有更好的排序表现。
如果经常需要在数字类型的字段上进行范围查询,可以考虑使用 TrieField,当索引越来越大时,它会提供更快的速度。

schema.xml 总结

schema.xml 第一级的结构如下所示:这个例子不是一个完整的 xml ,但是给出了这个文件重要的部分
&lt;schema&gt;<br />
&lt;types&gt;<br />
&lt;fields&gt;<br />
&lt;uniqueKey&gt;<br />
&lt;defaultSearchField&gt;<br />
&lt;solrQueryParser defaultOperator&gt;<br />
&lt;copyField&gt;<br />
&lt;/schema&gt;

其中最重要的是 types 和 fields,另外包括 复制字段、唯一键、默认查询操作符

其他 schema 元素–查询解析操作符

在使用多个条件进行查询时,Solr 可能返回满足所有条件的结构或者满足部分条件的结果。operator 控制这一行为,operator 包含 AND 和 OR,AND 将返回满足所有条件的结果,OR将返回满足任一条件的结果。
在 schema.xml,使用 solrQueryParser 元素来控制使用 AND 还是 OR。默认 operator 的设置只在 lucene 查询时生效,对于 DisMax 和扩展的 DisMax 无效,DisMax 和扩展 DisMax 内部采用硬编码的方式使用了 OR 操作。
<br />
&lt;solrQueryParser defaultOperator=&quot;OR&quot;/&gt;<br />

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress · 闽ICP备18020075号