什么是过滤器

和切词器一样,过滤器也是消费输入,然后输出一串的 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 />

其他 schema 元素–默认搜索字段

在使用lucene查询解析器时,如果没有指定字段名称,将在 defaultSearchField 进行查询。DisMax 和 扩展的 DisMax 查询解析中不会使用这个值。
定义默认查询字段格式如下:

&lt;defaultSearchField&gt;text&lt;/defaultSearchField&gt;

其中 text 为字段名称。

其他 schema 元素–uniqueKey

uniqueKey 元素用来表示一个文档的唯一值,类似数据库ID。尽管uniqueKey不是必须,但在程序设计过程中还是建议使用。举个例子,在更新一个文档时,需要通过uniqueKey来找到需要更新的文档。uniqueKey在schema中是这样定义的:

&lt;uniqueKey&gt;id&lt;/uniqueKey&gt;

动态字段

动态字段(Dynamic fields)允许 solr 索引没有在 schema 中明确定义的字段。这个在忘记定义一些字段时很有用。动态字段可以让系统更灵活,通用性更强。
动态字段和成规字段类似,除了它名字中包含一个通配符外,在索引文档时,一个字段如果在常规字段中没有匹配时,将到动态字段中匹配。
假设schema中定义了一个叫*_i的动态动态字段,如果要索引一个叫 cost_i 的字段,但是 schema 中不存在 cost_i 的字段,这样 cost_i  将被索引到 *_i 字段中。
动态字段也是定义在 schema.xml 文件中,和其他字段一样,它也有个名词,字段类型,和属性。

&lt;dynamicField name=&quot;*_i&quot; type=&quot;sint&quot; indexed=&quot;true&quot; stored=&quot;true&quot;/&gt;

建议在 schema.xml 定义一些基本的动态字段,以备扩展之用。

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