Schema设计 #

一、Schema概述 #

1.1 什么是Schema #

Schema定义了索引的结构,包括:

  • 字段定义(Field)
  • 字段类型(FieldType)
  • 动态字段(Dynamic Field)
  • 复制字段(Copy Field)
  • 唯一键(Unique Key)

1.2 Schema管理方式 #

Managed Schema(推荐)

  • 通过API动态修改
  • 自动保存到managed-schema文件
  • 支持Schema API

Classic Schema

  • 手动编辑schema.xml文件
  • 需要重载Core生效

1.3 Schema文件位置 #

text
mycore/
└── conf/
    ├── managed-schema    # 托管Schema
    └── schema.xml        # 传统Schema(可选)

二、字段定义 #

2.1 基本字段定义 #

xml
<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="price" type="pdouble" indexed="true" stored="true"/>
<field name="timestamp" type="pdate" indexed="true" stored="true"/>

2.2 字段属性详解 #

属性 类型 默认值 说明
name string 必填 字段名称
type string 必填 字段类型
indexed boolean true 是否索引
stored boolean true 是否存储
required boolean false 是否必需
multiValued boolean false 是否多值
docValues boolean false 是否使用DocValues
omitNorms boolean false 是否忽略规范
omitTermFreqAndPositions boolean false 是否忽略词频和位置
omitPositions boolean false 是否忽略位置
termVectors boolean false 是否存储词向量
termPositions boolean false 是否存储词位置
termOffsets boolean false 是否存储词偏移
termPayloads boolean false 是否存储词载荷
large boolean false 是否大字段

2.3 字段属性选择指南 #

indexed vs stored

场景 indexed stored
搜索字段 true true
仅搜索不展示 true false
仅展示不搜索 false true
排序字段 true false

docValues

xml
<!-- 排序、聚合、分组字段建议开启 -->
<field name="price" type="pdouble" indexed="true" stored="true" docValues="true"/>
<field name="category" type="string" indexed="true" stored="true" docValues="true"/>

2.4 Schema API添加字段 #

bash
# 添加字段
curl -X POST "http://localhost:8983/solr/mycore/schema" \
  -H "Content-Type: application/json" \
  -d '{
    "add-field": {
      "name": "author",
      "type": "text_general",
      "indexed": true,
      "stored": true
    }
  }'

# 批量添加字段
curl -X POST "http://localhost:8983/solr/mycore/schema" \
  -H "Content-Type: application/json" \
  -d '{
    "add-field": [
      {"name": "author", "type": "text_general"},
      {"name": "publisher", "type": "string"},
      {"name": "publish_date", "type": "pdate"}
    ]
  }'

三、动态字段 #

3.1 什么是动态字段 #

动态字段允许根据字段名模式自动匹配字段类型:

xml
<dynamicField name="*_i" type="pint" indexed="true" stored="true"/>
<dynamicField name="*_s" type="string" indexed="true" stored="true"/>
<dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
<dynamicField name="*_dt" type="pdate" indexed="true" stored="true"/>
<dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
<dynamicField name="*_f" type="pfloat" indexed="true" stored="true"/>
<dynamicField name="*_d" type="pdouble" indexed="true" stored="true"/>

3.2 使用示例 #

json
{
  "id": "product-001",
  "name_s": "iPhone 15",
  "price_d": 6999.00,
  "stock_i": 100,
  "in_stock_b": true,
  "created_dt": "2026-03-27T10:00:00Z",
  "description_t": "最新款iPhone"
}

3.3 Schema API添加动态字段 #

bash
curl -X POST "http://localhost:8983/solr/mycore/schema" \
  -H "Content-Type: application/json" \
  -d '{
    "add-dynamic-field": {
      "name": "*_txt",
      "type": "text_general",
      "indexed": true,
      "stored": true,
      "multiValued": true
    }
  }'

四、复制字段 #

4.1 什么是复制字段 #

复制字段将一个或多个字段的值复制到目标字段:

xml
<copyField source="title" dest="text"/>
<copyField source="content" dest="text"/>
<copyField source="author" dest="text"/>

4.2 使用场景 #

统一搜索

xml
<!-- 定义目标字段 -->
<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>

<!-- 复制多个字段 -->
<copyField source="title" dest="text"/>
<copyField source="content" dest="text"/>
<copyField source="tags" dest="text"/>

拼写检查

xml
<field name="spellcheck" type="text_spell" indexed="true" stored="false" multiValued="true"/>
<copyField source="title" dest="spellcheck"/>
<copyField source="content" dest="spellcheck"/>

4.3 Schema API添加复制字段 #

bash
curl -X POST "http://localhost:8983/solr/mycore/schema" \
  -H "Content-Type: application/json" \
  -d '{
    "add-copy-field": {
      "source": "title",
      "dest": ["text", "spellcheck"]
    }
  }'

五、字段类型 #

5.1 常用字段类型 #

字符串类型

xml
<fieldType name="string" class="solr.StrField" sortMissingLast="true"/>

数值类型

xml
<fieldType name="pint" class="solr.IntPointField" docValues="true"/>
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
<fieldType name="pfloat" class="solr.FloatPointField" docValues="true"/>
<fieldType name="pdouble" class="solr.DoublePointField" docValues="true"/>

日期类型

xml
<fieldType name="pdate" class="solr.DatePointField" docValues="true"/>

布尔类型

xml
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>

文本类型

xml
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

5.2 中文文本类型 #

IK分词器

xml
<fieldType name="text_ik" class="solr.TextField">
  <analyzer type="index">
    <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true"/>
  </analyzer>
</fieldType>

SmartChinese分词

xml
<fieldType name="text_smartcn" class="solr.TextField">
  <analyzer>
    <tokenizer class="solr.SmartChineseSentenceTokenizerFactory"/>
    <filter class="solr.SmartChineseStopTokenFilterFactory"/>
  </analyzer>
</fieldType>

5.3 自定义字段类型 #

bash
curl -X POST "http://localhost:8983/solr/mycore/schema" \
  -H "Content-Type: application/json" \
  -d '{
    "add-field-type": {
      "name": "text_custom",
      "class": "solr.TextField",
      "analyzer": {
        "tokenizer": {
          "class": "solr.StandardTokenizerFactory"
        },
        "filters": [
          {"class": "solr.LowerCaseFilterFactory"},
          {"class": "solr.StopFilterFactory", "words": "stopwords.txt"}
        ]
      }
    }
  }'

六、分析器配置 #

6.1 分析器组成 #

text
输入文本
    ↓
Tokenizer(分词器)
    ↓
Token Filter(过滤器)
    ↓
Token流

6.2 常用分词器 #

分词器 说明
StandardTokenizer 标准分词器
WhitespaceTokenizer 空格分词器
KeywordTokenizer 关键词分词器(不分词)
LetterTokenizer 字母分词器
PatternTokenizer 正则分词器
PathHierarchyTokenizer 路径分词器

6.3 常用过滤器 #

过滤器 说明
LowerCaseFilter 小写转换
StopFilter 停用词过滤
SynonymFilter 同义词扩展
StemmerFilter 词干提取
RemoveDuplicatesTokenFilter 去重
ASCIIFoldingFilter ASCII转换

6.4 完整分析器示例 #

xml
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.EnglishPossessiveFilterFactory"/>
    <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
    <filter class="solr.PorterStemFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.EnglishPossessiveFilterFactory"/>
    <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
    <filter class="solr.PorterStemFilterFactory"/>
  </analyzer>
</fieldType>

6.5 同义词配置 #

synonyms.txt

text
# 同义词配置
iphone,苹果手机
ipad,苹果平板
mbp,macbook pro

使用同义词

xml
<fieldType name="text_synonyms" class="solr.TextField">
  <analyzer>
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.SynonymGraphFilterFactory" 
            synonyms="synonyms.txt" 
            ignoreCase="true" 
            expand="true"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

6.6 停用词配置 #

stopwords.txt

text
# 停用词列表
a
an
and
are
as
at
be
but
by
for

七、唯一键 #

7.1 定义唯一键 #

xml
<uniqueKey>id</uniqueKey>

7.2 唯一键要求 #

  • 必须是stored字段
  • 建议使用string类型
  • 值不能为空

7.3 自动生成ID #

xml
<field name="id" type="string" indexed="true" stored="true" required="true"/>
<updateRequestProcessorChain name="uuid">
  <processor class="solr.UUIDUpdateProcessorFactory">
    <str name="fieldName">id</str>
  </processor>
  <processor class="solr.RunUpdateProcessorFactory"/>
</updateRequestProcessorChain>

八、Schema设计最佳实践 #

8.1 字段命名规范 #

xml
<!-- 推荐 -->
<field name="product_id" type="string"/>
<field name="product_name" type="text_general"/>
<field name="product_price" type="pdouble"/>

<!-- 不推荐 -->
<field name="id" type="string"/>
<field name="name" type="text_general"/>
<field name="price" type="pdouble"/>

8.2 字段类型选择 #

数据类型 推荐字段类型
ID string
标题 text_general
正文 text_general
分类 string
标签 string (multiValued)
价格 pdouble
数量 pint
日期 pdate
布尔 boolean

8.3 性能优化 #

减少stored字段

xml
<!-- 仅搜索不展示 -->
<field name="search_text" type="text_general" indexed="true" stored="false"/>

<!-- 仅展示不搜索 -->
<field name="description" type="string" indexed="false" stored="true"/>

使用DocValues

xml
<!-- 排序、聚合字段 -->
<field name="price" type="pdouble" indexed="true" stored="true" docValues="true"/>
<field name="category" type="string" indexed="true" stored="true" docValues="true"/>

合理使用multiValued

xml
<!-- 多值字段 -->
<field name="tags" type="string" indexed="true" stored="true" multiValued="true"/>

九、Schema API完整示例 #

9.1 创建完整Schema #

bash
curl -X POST "http://localhost:8983/solr/mycore/schema" \
  -H "Content-Type: application/json" \
  -d '{
    "add-field-type": {
      "name": "text_cn",
      "class": "solr.TextField",
      "analyzer": {
        "tokenizer": {"class": "solr.StandardTokenizerFactory"},
        "filters": [
          {"class": "solr.LowerCaseFilterFactory"}
        ]
      }
    },
    "add-field": [
      {"name": "id", "type": "string", "indexed": true, "stored": true, "required": true},
      {"name": "title", "type": "text_cn", "indexed": true, "stored": true},
      {"name": "content", "type": "text_cn", "indexed": true, "stored": true},
      {"name": "author", "type": "string", "indexed": true, "stored": true},
      {"name": "price", "type": "pdouble", "indexed": true, "stored": true, "docValues": true},
      {"name": "category", "type": "string", "indexed": true, "stored": true, "docValues": true},
      {"name": "tags", "type": "string", "indexed": true, "stored": true, "multiValued": true},
      {"name": "publish_date", "type": "pdate", "indexed": true, "stored": true},
      {"name": "text", "type": "text_cn", "indexed": true, "stored": false, "multiValued": true}
    ],
    "add-copy-field": [
      {"source": "title", "dest": "text"},
      {"source": "content", "dest": "text"},
      {"source": "author", "dest": "text"}
    ]
  }'

9.2 查看Schema #

bash
curl "http://localhost:8983/solr/mycore/schema?wt=json"

9.3 删除字段 #

bash
curl -X POST "http://localhost:8983/solr/mycore/schema" \
  -H "Content-Type: application/json" \
  -d '{
    "delete-field": {"name": "old_field"}
  }'

十、Schema版本管理 #

10.1 导出Schema #

bash
curl "http://localhost:8983/solr/mycore/schema?wt=json" > schema_backup.json

10.2 版本控制 #

bash
# 复制Schema到版本控制目录
cp server/solr/mycore/conf/managed-schema /path/to/repo/

# 使用Git管理
git add managed-schema
git commit -m "Update schema"

十一、总结 #

Schema设计要点:

要点 说明
字段定义 合理设置indexed、stored、docValues
动态字段 使用动态字段简化Schema
复制字段 统一搜索字段
字段类型 选择合适的字段类型
分析器 配置合适的分词器和过滤器

最佳实践:

  • 使用Schema API管理Schema
  • 合理设置字段属性
  • 使用DocValues优化排序聚合
  • 使用动态字段灵活扩展
  • 定期备份Schema

下一步,让我们学习文档操作!

最后更新:2026-03-27