Solr 03 - Solr的模式设计与优化 - 最详细的schema.xml模式文件解读
1 关于schema.xml文件
Solr将数据以结构化的形式存储到文件系统中, 在存储的过程中对数据建立索引 —— 通过模式文件schema.xml文件来定义这个结构.
schema.xml
文件位于Solr安装包的example/solr/collection1/conf/
目录下, 主要用于配置Solr的域(Field)以及域的类型(FieldType).
说明事项:
① Solr中Field相关内容要先配置再使用;
② schema.xml文件的名称不可以更改;
③ 在使用中也应该位于SolrHome/conf/
下 或者位于 Solr Web 应用的类加载器可以加载到的位置.
这里演示的
schema.xml
文件是Solr 4.10.4版本中的模式文件.
2 解读schema.xml文件
文件示例:
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="user" version="1.5">
<field name="_version_" type="long" indexed="true" stored="true"/>
<field name="_root_" type="string" indexed="true" stored="false"/>
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="name" type="text_general" indexed="true" stored="true"/>
<uniqueKey>id</uniqueKey>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
</analyzer>
</fieldType>
</schema>
(1) 根元素是schema, name属性值用来展示, 可以任意配置, version是Solr模式语法和语义的版本号, Solr 4.10版本中使用1.5版本.
1.0版本: multiValued属性不存在, 所有字段本质上都是多值的;
1.1版本: 引入了multiValued属性, 默认为false;
1.2版本: 引入了omitTermFreqAndPositions属性, 默认为true, 文本字段除外;
1.3版本: 删除了可选的字段压缩功能;
1.4版本: autoGeneratePhraseQueries属性, 用于在单个字符串生成多个标记时驱动QueryParser行为. 1.4及以上的版本默认关闭;
1.5版本: 对于原始字段类型(如int, float, boolean, string...), omitNorms默认为true.
(2)根元素下主要有field和fieldType两个标签, 分别用来定义域和域的类型.
2.1 field - 配置域
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
field
类似于MySQL中数据表的字段, 属性包括name, type(就是之前定义过的fieldType
)等等, 具体属性说明如下:
(1)必需属性:
①
name
: 域的名称, 以字母或下划线开头, 不能由数字开头;
②type
: 下面将定义的fieldType域的类型;
③indexed
: 如果此字段需要被检索和排序, 就设置为true;
④stored
: 如果这个字段在查询的时候需要显示出来, 就要设置为true, 表示存储它的原始值, 如果在检索的时候不需要显示原始值, 就尽量设置为false, 尤其是值比较大的字段;
⑤required
: 表明该字段是必填字段, 类似于MySQL中的not null. 若设置为true, 在创建索引时, 就必须包含该字段的值, 如过不存在, 就会抛出错误;
⑥multiValued
: 是否有多个值(在Solr中允许一个域保存多个值, 类似于MySQL中一个用户可以存储多个好友, 一件商品有多个细节图片).
原配置文件中的英文说明:
Although it would make indexing slightly slower and the index bigger, it would also make the index faster to load, more memory-efficient and more NRT-friendly.
大概意思是: 虽然它会使索引略微变慢、索引文件变得更大, 但它却能使得索引更快被加载, 内存使用效率更高, 并且更友好的NRT(近实时搜索).
(2)可选属性:
①
docValues
: 是否为当前field添加一个名为docValues的field --- 这对facet查询、group分组、排序、function查询有好处.a) 不足: 会使得索引过程略慢, 且索引文件更大;
b) 优点: 能加快索引数据的加载, 对NRT(近实时搜索)也更加友好, 而且更节省内存;
c) 限制: 目前docValues只支持strField、UUIDField、Trie*Field; 要求字段的值是单值, 并且此field的值必须存在或具有默认值.②
compressed
: 是否使用gzip压缩(只有TextField和StrField可以压缩), 默认为false;③
omitNorms
(专业属性): 是否忽略掉Norm, 如果设置为true, 将忽略与此字段相关联的规范 (这将禁用字段的长度规范化和检索时文档权重分的提升, 并节省一些内存空间). 只有全文本的field和需要检索时提升权重的field需要norm; 只有全文本类型的字段, 或者需要在检索时对当前字段的权重进行设置时, 才需要相关规范, 此时需要将其设置为false. 默认情况下, 原始(未分析)类型的规范将被忽略.④
termVectors
: 默认false, 为true时会存储当前字段的term vector(术语向量), 使用MoreLikeThis时, 用来作为相似性匹配的field的stored应该设置为true, 以提高性能;⑤
termPositions
: 使用term vector存储位置信息, 这会增大存储成本;⑥
termOffsets
: 使用term vector存储偏移量信息, 这会增大存储成本;⑦
default
: 设置当前字段的默认值, 如果在添加文档时没有为该字段指定值, 将使用此默认值.
(3)注意事项:
①
name="_version_"
的字段必须添加, 用来记录Solr中文档的版本. 如果删除此字段, 则必须禁用solrconfig.xml
文件中的更新日志, 否则Solr将无法启动. SolrCloud需要_version_
和更新日志.②
name="_root_"
的字段用来指向嵌套文档块的根文档, 有嵌套文档时就必需存在此字段, 否则嵌套文档可能会被删除.③ 几乎所有的Solr文档中都存在
<uniqueKey>id</uniqueKey>
—— 主键为id, 如果没有充分的理由, 请不要删除id字段. ⇒ 当然可以根据实际情况配置符合自身业务的主键.
2.2 fieldType - 配置域类型
fieldType供Solr内部使用, 不支持自定义域类型. 原始FieldType定义示例:
<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" />
<!-- in this example, we will only use synonyms at query time <filter class="solr.SynonymFilterFactory"
synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/> -->
<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>
</fieldType>
(1)必需属性:
①
name
: 域类型的名称, 是field中的type;
②class
: 域类型对应的Solr的标准Java类, 以"Solr"开头的class是org.apache.solr.analysis
包中的Java类;
③ analyzer: 定义索引和搜索使用的分词器, **是核心配置 --- 使用的分析器不同, 索引和检索也将不同**; ④
type: index(索引流程)和query(检索流程); ⑤
tokenizer: 指定具体使用的分词器; ⑥
filter`: 指定使用的过滤器;
(2)可选属性:
①
positionIncrementGap
: 当multiValued="true"
时使用, 定义在同一个文档中此类型数据的空白间隔, 即设置多个值之间的虚拟空白的数量, 避免短语匹配错误.②
autoGeneratePhraseQueries
: 有点类似找近义词或者自动纠错, 例如可以将 "wi fi" 自动转为 "wifi" 或 "wi-fi", 如果不设置这个属性则需要在查询时强制加上引号, 如 'wi fi';③
sortMissingLast
/sortMissingFirst
: 对查询结果进行排序的过程中, 如果发现这个字段的值不存在, 就排在前面/后面, 忽略排序的条件. 使用方式如下:a) 默认值均为false, 将使用Lucene内部的排序规则: 将没有该字段的文档放在升序中, 最后放在降序结果中. ;
b)sortMissingLast="true"
, 对该字段进行排序时, 没有该字段的文档将排在有该字段的文档的后面, 忽略请求时的排序规则(asc或desc);
c)sortMissingFirst="true"
, 与sortMissingLast
作用相反.
(3)常见域类型(class):
① solr.StrField
:
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
此类型不会被分词, 而是被逐字索引/存储. 它支持docValues域, 如果使用此fieldType的field添加了docValues字段, 则要求该field只能是单值域且该域必须存在或者该域有默认值.
② solr.BoolField
:
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
boolean域, 对应true/false.
③ solr.Trie*Field
: 默认的数字域类型:
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
这些字段支持docValues, 但它们要求field为单值, 并且要么是必需的, 要么具有默认值.
④ solr.Trie*Field
: 更快的范围查询的数字域类型:
如果需要更快的范围查询, 请考虑 tint / tfloat / tlong / tdouble
类型:
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
此类型 以多种精度级别对每个值创建不同的索引 , 用来加速范围两端间距较大时的范围查询.
precisionStep
: 一般用于数字范围查询, 其值越小(以位为单位), 索引时该域的值分出的token个数越多 ⇒ 索引体积会稍大(slightly larger index size) ⇒ 但这能加快数字范围检索的响应速度.
precisionStep="0"
将禁用不同精度级别的索引.
positionIncrementGap
: 如果当前域是多值域时, 多个值之间的间距. 该属性在单值域上无意义.
⑤ solr.TrieDateField
: 日期域类型:
<fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
日期字段只支持格式为1995-12-31T23:59:59Z的日期, 最后的 Z
表示UTC时间, 并且必须是UTC时间.
其中, 只有秒数可以选用小数: 1995-12-31T23:59:59.999Z, 其他部分都是必需且格式不能改变的.
日期表达式也可用于表示相对于"NOW"(当前时刻)的时间, 如:
NOW/HOUR
⇒ 回到当前小时的开始时间;
NOW-1DAY
⇒ 恰好在前一天;
NOW/DAY+6MONTHS+3DAYS
⇒ 从当天开始, 将来6个月零3天的时刻.
注意: 对于更快的范围的查询和日期分面的需求, 请考虑使用tdate类型.
<fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
⑥ solr.BinaryField
:
<fieldtype name="binary" class="solr.BinaryField"/>
经过Base64编码的字符串域类型, 就是说需要把数据进行Base64编码, 然后再发送/检索.
⑦ solr.RandomSortField
:
<fieldType name="random" class="solr.RandomSortField" indexed="true" />
随机排序域类型, 不用于存储或搜索任何数据, 可以在模式中声明此类型的字段, 以实现文档的伪随机排序.
⇒ 根据字段名称和索引的版本生成排序. 只要索引的版本
_version_
不变, 并且重用相同的字段名称, 文档的顺序就会一致.
⇒ 如果需要不同的伪随机文档排序, 对于相同版本的索引, 请使用dynamicField并更改请求中的字段名称.
⑧ solr.TextField
:
使用最多的一种域类型, 需要分词, 一般需要用户配置分析器来定制索引和查询, 分析器包括一个分词器(tokenizer)和多个过滤器(filter). 示例:
<!-- 空格分词器, 精确匹配:
在向索引库添加text类型的索引时, Solr会首先用空格进行分词,
然后把分词结果依次使用指定的过滤器进行过滤,
最后剩下的结果才会加入到索引库中以备查询.
注意: Solr的analysis包并没有支持中文的包, 需要自己添加中文分词器.
-->
<fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory" />
</analyzer>
</fieldType>
(4)常见的过滤器(filter):
① 分隔符过滤器:
<!-- 在分词和匹配时, 考虑 "-"连字符, 字母数字的界限, 非字母数字字符,
这样"wifi"或"wi fi"都能匹配"Wi-Fi".
-->
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1"
generateNumberParts="1" catenateWords="1" catenateNumbers="1"
catenateAll="0" splitOnCaseChange="1" />
② 同义词过滤器:
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
ignoreCase="true" expand="true" />
③ 停词(禁用词)过滤器:
<!-- 在禁用字(stopword)删除后, 在短语间增加间隔stopword:
即在建立索引过程中(建立索引和搜索)被忽略的词, 比如is this等常用词.
在conf/stopwords.txt文件中设置维护.
-->
<filter class="solr.StopFilterFactory" ignoreCase="true"
words="stopwords.txt" enablePositionIncrements="true" />
2.3 copyField - 配置复制域
Solr允许将多个域的值, 复制给一个域, 目的是方便搜索.
比如: 搜索含有"Solr"的文档, 需要把标题、摘要信息、正文中含有"Solr"的文档都查询出来, 有了copyField
域, 就只需要搜索copyField
域, 而不需要写全标题、摘要信息、正文三个域的值.
在创建索引的时候, Solr会将源域的内容, 复制给目标域.
<copyField source="cat" dest="text"/>
(1)属性说明:
①
source
: 源域的名称;
②dest
: 目标域的名称, 搜索时指定目标域为默认搜索域, 可提高查询效率.
(2)使用注意事项:
① 目标域的定义, 必须要指定
multiValued="true"
.
② 只复制单个域, 如果被复制域本身就是多值域, 那么目标域也是多值域 ⇒ 无实际意义;
③ 若复制多个域, 只要其中有一个域是多值域, 那么目标域就一定是多值域.
2.4 dynamicField - 配置动态域
动态域通过通配符, 实现了域的模糊匹配, 能够有效避免频繁地修改schema.xml
文件.
⇒ 修改schema.xml文件后, Solr程序需要重新加载配置文件, 较为繁琐.
dynamicField
(动态域) 和 copyField
(复制域)是Solr扩展的域, 在Lucene中没有与之相关的概念.
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
(1)属性说明:
name
: 动态域的名称, 是一个表达式:a)
*
表示匹配任意字符, 只能出现在模式的最前或最后;
b) 较长的模式会先做匹配;
c) 如果2个模式同时匹配上, 最先定义的优先匹配.
(2)使用说明:
使用时, 只需要域的名称与表达式匹配即可. 如
"product_i":"笔记本"
, 直接使用product_i就可以, 不需要再做其他定义.
如果通过上面的匹配都没找到, 可以设置下述类型的配置, 然后定义一个type当作String处理. 一般不会发生, 但若不定义, 找不到匹配就会报错.<dynamicField name="*_i" type="ignored" multiValued="true"/>
2.5 uniqueKey - 配置唯一标识
Solr通过uniqueKey
来指定文档的主键, 默认的, id域被作为主键, 因此id域是必须的.
⇒ 当然用户可以自定义主键.
<uniqueKey>id</uniqueKey>
Solr中被标记为required="true"
的字段, 必须要由<uniqueKey>
作唯一标识, 否则建立索引时将报错.
Solr将根据<uniqueKey>
标识的field (默认就是id) 来决定增量导入时是否重复导入: 如果id相同, 就不会重复导入;
2.6 其他配置说明
(1) 默认搜索域:
<defaultSearchField>text</defaultSearchField>
如果搜索参数中没有指定具体的field, 这将作为默认的域进行搜索.
Solr 6.x版本中已经移除了此参数.
(2) Solr查询解析器:
<!-- 从Solr 6.6版本开始, 不再支持defaultOperator -->
<solrQueryParser defaultOperator="OR"/>
配置搜索参数短语间的逻辑, 可以是AND|OR.
3 关于schema.xml的优化
3.1 field的配置技巧
(1) 将所有只用于搜索、而不需要作为结果返回原始值的field(特别是比较大的field)设置为 stored="false"
;
(2) 将不需要被用于搜索、而只是作为结果返回的field设置为 indexed="false"
;
(3) 删除所有不必要的copyField;
(4) 为了最小化索引字段、提高搜索效率, 将为所有的text field 都设置 index="false"
, 然后使用copyField将它们都复制到一个总的text field上, 对该text field进行搜索;
(5) 为了最大化搜索性能, 使用ConcurrentUpdateSolrServer
Java客户端与Solr交互(使用并发修改服务);
(6) 在服务器端运行JVM, 即设置使用-server
服务端模式, 性能更好; 并使用尽可能高级别的Log输出等级, 避免记录每个请求, 减少日志量.
3.2 field的配置示例
分词 | 搜索 | 存储 | 示例 |
---|---|---|---|
√ | √ | √ | 网页的标题、内容 |
√ | X | √ | 网页的发布时间 |
X | X | √ | 引用的图片位置 |
√ | √ | √ | 网页标题、内容 |
不存在不需要索引、不需要分词、也不需要存储的字段, 因为这样的字段在Lucene中无意义.
参考资料
版权声明
出处: 博客园 马瘦风的博客(https://www.cnblogs.com/shoufeng)
感谢阅读, 如果文章有帮助或启发到你, 点个[好文要顶
Solr 03 - Solr的模式设计与优化 - 最详细的schema.xml模式文件解读的更多相关文章
- solr中的schema.xml(managed-schema)文件解读
solr 7.2.1版本managed-schema文件示例 <uniqueKey>id</uniqueKey> 唯一键字段,solr对每一个文档都赋予一个唯一标识符字段,避免 ...
- Solr记录-solr基础内容
Solr架构(体系结构) 在本章中,我们将讨论Apache Solr的架构. 下图显示了Apache Solr的体系结构的框图. Solr架构 - 构件块以下是Apache Solr的主要构建块(组件 ...
- Solr 15 - Solr添加和更新索引的过程 (文档的路由细节)
目录 1 添加文档的细节 1.1 注册观察者 - watcher 1.2 文档的路由 - document route 1.2.1 路由算法 1.2.2 Solr路由的实现类 1.2.3 implic ...
- Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)(1)
刚学Solr(版本6.7.0),新建一个core时,提示要求schema.xml文件,我找了半天也没在源码包中找到名为schema.xml的文件.这个版本其实用的是managed-schema文件,没 ...
- 利用SOLR搭建企业搜索平台 之——模式配置Schema.xml
来源:http://blog.csdn.net/awj3584/article/details/16963525 schema.xml这个配置文件可以在你下载solr包的安装解压目录的\solr\ex ...
- Solr 11 - Solr集群模式的部署(基于Solr 4.10.4搭建SolrCloud)
目录 1 SolrCloud结构说明 2 环境的安装 2.1 环境说明 2.2 部署并启动ZooKeeper集群 2.3 部署Solr单机服务 2.4 添加Solr的索引库 3 部署Solr集群服务( ...
- Solr 02 - 最详细的solrconfig.xml配置文件解读
目录 1 luceneMatchVersion - 指定Lucene版本 2 lib - 配置扩展jar包 3 dataDir - 索引数据路径 4 directoryFactory - 索引存储工厂 ...
- Solr Schema.xml和solrconfig.xml分析(转)
Solr Schema.xml和solrconfig.xml分析 (http://yinwufeng.iteye.com/blog/964040) 一.字段配置(schema) schema.xml位 ...
- Solr 07 - Solr从MySQL数据库中导入数据 (Solr DIH的使用示例)
目录 1 加入数据导入处理器的jar包 2 加入数据库驱动包 3 配置solrconfig.xml文件 3.1 配置lib标签 - 加入驱动jar包 3.2 配置requestHandler标签 - ...
随机推荐
- swool配置ssl
1 yum install openssl --enable-openssl -y 2 切换在swoole 安装目录 cd /usr/local/swoole 3 ./configure --en ...
- Love Live!-01字典树启发式合并
链接:https://ac.nowcoder.com/acm/contest/201/D?&headNav=www 思路:题目要求的是每个等级下的最大 简单路径中的最大异或值,那么我们为了保证 ...
- Java对象转换成Map
需求总是千奇百怪,对象转成map,看似没必要,但就是有这个需求,所以记录下来 首先是Bean package tools; import lombok.Data; /** * 车辆实体类 */ @Da ...
- pip install –r ./requirements.txt 报错 改成 pip install -r requirements.txt 成功
Invalid requirement: '–r'Traceback (most recent call last): File "/home/dev/.pyenv/versions/3.6 ...
- java内存结构
Java的内存结构 JVM的内存结构主要有三大块:堆.方法区和栈.堆内存是JVM中最大的一块,由年轻代和老年代组成,而年轻代内存又被分为三部分,Eden空间.FromSurvivor空间和ToSurv ...
- swust oj 1016
插入排序算法实现 1000(ms) 10000(kb) 2613 / 6080 插入排序算法实现. 输入 第一行是待排序数据元素的个数: 第二行是待排序的数据元素. 输出 一趟直接插入排序算法结果. ...
- C语言复习4_while循环
1.while循环 循环三要素: 1).循环变量的初值 2).循环变量的判断 3).循环变量的更新 #include <stdio.h> #include <stdlib.h> ...
- 二分- Count on Canton
题目: 代码: 是一个蛇形数列,把题目上的那组数倒过来看成一个正三角形. 第一行有1个数,1-2行有三个数,1-4行有6个数,1-4行有10个数,1-5行有15个数..... 现在要求第n个数是多少, ...
- Java作业八(2017-10-30)
public class TAutoPerson { public static void main(String args[]) { new Person(); new Person(); new ...
- High Availability手册(1): 环境
三台KVM虚拟机 首先我们得有一个pacemaker的环境,需要三台机器,如果没有那么多物理机器,可以用kvm虚拟机 创建一个bridge ovs-vsctl add-br ubuntu_br ifc ...