Solr索引:Schema元素结构与核心配置详解
Solr在schema文件中存储关于它期望理解的字段类型和字段的详细信息。
Solr的Schema文件
Schema文件的名称和位置可能根据你最初配置Solr的方式或后来修改的情况而有所不同。
文件命名约定
managed-schema.xml
- Solr默认使用的schema文件名称
- 支持通过Schema API或无模式模式在运行时进行模式更改
- 你可以明确配置托管模式功能使用替代文件名,但文件内容仍由Solr自动更新
schema.xml
- 传统的schema文件名称
- 可由使用
ClassicIndexSchemaFactory
的用户手动编辑
SolrCloud环境
- 如果使用SolrCloud,可能无法在本地文件系统上找到这些名称的任何文件
- 只能通过Schema API(如果启用)或通过Solr管理界面的云屏幕查看schema
交互方式
无论安装中使用的文件名称如何,文件的结构都不会改变。但是,与文件交互的方式会改变:
- 托管模式:预期仅通过Schema API与文件交互,永远不要手动编辑
- 传统模式:只能对文件进行手动编辑,Schema API不支持任何修改
如果你不使用Schema API但确实使用SolrCloud,你需要通过ZooKeeper使用upconfig
和downconfig
命令与schema文件交互,制作本地副本并上传你的更改。
Schema文件的结构
以下是schema文件的主要元素结构:
1 2 3 4 5 6 7 8 9 10
| <schema> <types> <fieldType> <fields> <field> <copyField> <dynamicField> <similarity> <uniqueKey> </schema>
|
核心元素说明
最常定义的元素是types
和fields
,其中配置字段类型和实际字段:
- types:字段类型定义
- fields:具体字段配置
- copyField:字段复制规则
- dynamicField:动态字段定义
- similarity:相似度算法配置
- uniqueKey:唯一键定义
⚠️ 灵活性提醒:types
和fields
部分是可选标签,你可以在顶层自由混合field
、dynamicField
、copyField
和fieldType
定义。这允许在你的schema中更逻辑地分组相关元素。
唯一键(Unique Key)
uniqueKey
元素指定哪个字段是文档的唯一标识符。虽然uniqueKey
不是必需的,但几乎总是由应用程序设计保证。例如,如果你将要在索引中更新文档,则应该使用uniqueKey
。
唯一键定义
1
| <uniqueKey>id</uniqueKey>
|
重要限制
- Schema默认值和
copyFields
不能用于填充uniqueKey
字段
uniqueKey
的fieldType
不得被分析,且不得是任何*PointField
类型
- 如果
uniqueKey
字段是多值的(或从fieldtype继承多值性),操作将失败
- 可以使用
UUIDUpdateProcessorFactory
自动生成uniqueKey
值
实际配置示例
1 2 3 4 5 6 7 8 9 10 11 12
| <field name="id" type="string" indexed="true" stored="true" required="true"/> <uniqueKey>id</uniqueKey>
<field name="uuid" type="uuid" indexed="true" stored="true" default="NEW"/> <uniqueKey>uuid</uniqueKey>
<field name="composite_id" type="string" indexed="true" stored="true"/> <uniqueKey>composite_id</uniqueKey>
|
相似度算法(Similarity)
相似度是在搜索中对文档评分的Lucene类。
默认行为
每个集合都有一个”全局”相似度。默认情况下,Solr使用隐式的SchemaSimilarityFactory
,它:
- 允许为单个字段类型配置”每类型”特定的相似度
- 对任何没有明确相似度的字段类型隐式使用
BM25Similarity
全局相似度配置
直接类引用
1
| <similarity class="org.apache.lucene.search.similarities.BM25Similarity"/>
|
使用相似度工厂
1
| <similarity class="solr.BM25SimilarityFactory"/>
|
带参数的相似度工厂
1 2 3 4 5 6
| <similarity class="solr.DFRSimilarityFactory"> <str name="basicModel">P</str> <str name="afterEffect">L</str> <str name="normalization">H2</str> <float name="c">7</float> </similarity>
|
字段类型特定相似度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <similarity class="solr.SchemaSimilarityFactory"> <str name="defaultSimFromFieldType">text_dfr</str> </similarity>
<fieldType name="text_dfr" class="solr.TextField"> <analyzer> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> <similarity class="solr.DFRSimilarityFactory"> <str name="basicModel">I(F)</str> <str name="afterEffect">B</str> <str name="normalization">H3</str> <float name="mu">900</float> </similarity> </fieldType>
<fieldType name="text_bm25" class="solr.TextField"> <analyzer> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> <similarity class="solr.BM25SimilarityFactory"> <float name="k1">1.2</float> <float name="b">0.75</float> </similarity> </fieldType>
|
常用相似度算法
1. BM25相似度(推荐)
1 2 3 4
| <similarity class="solr.BM25SimilarityFactory"> <float name="k1">1.2</float> <float name="b">0.75</float> </similarity>
|
2. DFR相似度
1 2 3 4 5 6
| <similarity class="solr.DFRSimilarityFactory"> <str name="basicModel">G</str> <str name="afterEffect">L</str> <str name="normalization">H2</str> <float name="c">7</float> </similarity>
|
3. IB相似度
1 2 3 4 5
| <similarity class="solr.IBSimilarityFactory"> <str name="distribution">LL</str> <str name="lambda">DF</str> <str name="normalization">H2</str> </similarity>
|
4. LMDirichlet相似度
1 2 3
| <similarity class="solr.LMDirichletSimilarityFactory"> <float name="mu">2000</float> </similarity>
|
完整Schema示例
以下是一个完整的schema配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| <?xml version="1.0" encoding="UTF-8"?> <schema name="example-schema" version="1.6"> <similarity class="solr.SchemaSimilarityFactory"> <str name="defaultSimFromFieldType">text_general</str> </similarity> <fieldType name="string" class="solr.StrField" sortMissingLast="true"/> <fieldType name="int" class="solr.IntPointField" docValues="true"/> <fieldType name="long" class="solr.LongPointField" docValues="true"/> <fieldType name="float" class="solr.FloatPointField" docValues="true"/> <fieldType name="double" class="solr.DoublePointField" docValues="true"/> <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/> <fieldType name="date" class="solr.DatePointField" docValues="true"/> <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.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> <similarity class="solr.BM25SimilarityFactory"> <float name="k1">1.2</float> <float name="b">0.75</float> </similarity> </fieldType> <field name="id" type="string" indexed="true" stored="true" required="true"/> <field name="title" type="text_general" indexed="true" stored="true"/> <field name="content" type="text_general" indexed="true" stored="true"/> <field name="category" type="string" indexed="true" stored="true" multiValued="true"/> <field name="price" type="float" indexed="true" stored="true"/> <field name="in_stock" type="boolean" indexed="true" stored="true"/> <field name="publish_date" type="date" indexed="true" stored="true"/> <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/> <dynamicField name="*_i" type="int" indexed="true" stored="true"/> <dynamicField name="*_s" type="string" indexed="true" stored="true"/> <dynamicField name="*_l" type="long" indexed="true" stored="true"/> <dynamicField name="*_t" type="text_general" indexed="true" stored="true"/> <dynamicField name="*_b" type="boolean" indexed="true" stored="true"/> <dynamicField name="*_f" type="float" indexed="true" stored="true"/> <dynamicField name="*_d" type="double" indexed="true" stored="true"/> <dynamicField name="*_dt" type="date" indexed="true" stored="true"/> <dynamicField name="*_txt" type="text_general" indexed="true" stored="true"/> <copyField source="title" dest="text"/> <copyField source="content" dest="text"/> <copyField source="category" dest="text"/> <uniqueKey>id</uniqueKey> </schema>
|
最佳实践
1. 版本管理
1 2 3
| <schema name="myapp-schema" version="1.6"> </schema>
|
2. 字段组织
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
<field name="id" type="string" indexed="true" stored="true" required="true"/> <field name="timestamp" type="date" indexed="true" stored="true" default="NOW"/>
<field name="title" type="text_general" indexed="true" stored="true"/> <field name="content" type="text_general" indexed="true" stored="true"/>
<field name="category" type="string" indexed="true" stored="true" multiValued="true"/> <field name="tags" type="string" indexed="true" stored="true" multiValued="true"/>
<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
|
3. 性能优化配置
1 2 3 4 5 6 7 8 9 10 11
| <fieldType name="text_fast" class="solr.TextField" omitNorms="true" omitTermFreqAndPositions="true"> <analyzer> <tokenizer class="solr.KeywordTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> </fieldType>
<field name="sort_field" type="string" indexed="false" stored="false" docValues="true"/> <field name="facet_field" type="string" indexed="true" stored="false" docValues="true"/>
|
4. 安全和维护
1 2 3 4 5 6 7 8
|
<schema name="production-schema" version="1.6"> </schema>
|
总结
Solr的schema设计是构建高效搜索应用的基础。通过合理配置字段类型、字段属性、唯一键和相似度算法,可以实现最优的索引性能和搜索体验。在实际应用中,应根据数据特点和查询需求进行精心设计,同时保持良好的维护和版本控制实践。