一、Schema介紹
1. Schema 是什么?
Schema:模式,是集合/內核中字段的定義,讓solr知道集合/內核包含哪些字段、字段的數據類型、字段該索引存儲。
2. Schema 的定義方式
Solr中提供了兩種方式來配置schema,兩者只能選其一
2.1 默認方式,通過Schema API 來實時配置,模式信息存儲在內核目錄的conf/managed-schema文件中。
2.2 傳統的手工編輯conf/schema.xml的方式,編輯完后需重載集合/內核才會生效。
3. schema兩種配置方式切換
3.1 schema.xml 到 managed schema
只需將 solrconfig.xml中的<schemaFactory class =“ClassicIndexSchemaFactory”/> 去掉,或改為ManagedIndexSchemaFactory
Solr重啟時,它發現存儲schema.xml 但不存儲在 managed-schema,它會備份schema.xml,然后改寫schema.xml 為 managed-schema。此后就可以通過Schema API 管理schema了。
3.2 managed schema 到 schema.xml
1 將managed-schema 重命名為 schema.xml
2 將solrconfig.xml 中schemaFactory 的ManagedIndexSchemaFactory去掉(如果存在)
3 增加<schemaFactory class =“ClassicIndexSchemaFactory”/>
4. 查看 D:\solr-7.3.0\server\solr\mycore\conf\managed-schema文件,了解它的構成
二、字段定義詳解
1. 字段定義示例
<field name="name" type="text_general" indexed="true" stored="true"/> <field name="includes" type="text_general" indexed="true" stored="true" termVectors="true" termPositions="true" termOffsets="true" />
字段屬性說明
name:字段名,必需。字段名可以由字母、數字、下划線構成,不能以數字開頭。以下划線開頭和結尾的名字為保留字段名,如 _version_
type:字段的fieldType名,必需。為 FieldType定義的name 屬性值。
default:默認值,如果提交的文檔中沒有該字段的值,則自動會為文檔添加這個默認值。非必需。
2. 字段定義詳解-定義FieldType
(前面定義了字段field,這里我們就有定義字段類型fieldtype來給字段使用了)
字段類型,定義在索引時該如何分詞、索引、存儲字段,在查詢時該如何對查詢串分詞
<fieldType name="managed_en" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.ManagedStopFilterFactory" managed="english" /> <filter class="solr.ManagedSynonymGraphFilterFactory" managed="english" /> <filter class="solr.FlattenGraphFilterFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.ManagedStopFilterFactory" managed="english" /> <filter class="solr.ManagedSynonymGraphFilterFactory" managed="english" /> </analyzer> </fieldType>
FieldType 的屬性
Solr中提供的 FieldType 類,在 org.apache.solr.schema 包下
http://lucene.apache.org/solr/guide/7_3/field-types-included-with-solr.html
3. FieldType 的 Analyzer
對於 solr.TextField or solr.SortableTextField 字段類型,需要為其定義分析器。
<fieldType name="nametext" class="solr.TextField"> <analyzer class="org.apache.lucene.analysis.core.WhitespaceAnalyzer"/> </fieldType>
可以直接通過class屬性指定分析器類,必須繼承org.apache.lucene.analysis.Analyzer 。
也可靈活地組合分詞器、過濾器:
<fieldType name="nametext" class="solr.TextField"> <analyzer> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StandardFilterFactory"/> <filter class="solr.LowerCaseFilterFactory"/> <filter class="solr.StopFilterFactory"/> </analyzer> </fieldType>
注意:org.apache.solr.analysis 包下的類可以簡寫為 solr.xxx
如果該類型字段索引、查詢時需要使用不同的分析器,則需區分配置analyzer
<fieldType name="nametext" class="solr.TextField"> <analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> <filter class="solr.KeepWordFilterFactory" words="keepwords.txt"/> <filter class="solr.SynonymFilterFactory" synonyms="syns.txt"/> </analyzer> <analyzer type="query"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> </fieldType>
Solr中提供的tokenizer: http://lucene.apache.org/solr/guide/7_3/tokenizers.html
Solr中提供的 fiter: http://lucene.apache.org/solr/guide/7_3/filter-descriptions.html
4. 常用的Filter
4.1 Stop Filter 停用詞過濾器
<analyzer> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StopFilterFactory" words="stopwords.txt"/> </analyzer>
words屬性指定停用詞文件的絕對路徑或相對 conf/目錄的相對路徑
停用詞定義語法:一行一個
4.2 Synonym Graph Filter 同義詞過濾器
<analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.SynonymGraphFilterFactory" synonyms="mysynonyms.txt"/> <filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters --> </analyzer> <analyzer type="query"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.SynonymGraphFilterFactory" synonyms="mysynonyms.txt"/> </analyzer>
同義詞定義語法:
(1)一類一行:
couch,sofa,divan
(2)=>表示標准化為后面的:
teh => the
huge,ginormous,humungous => large
small => tiny,teeny,weeny
提問:(1)(2)同義詞的定義在索引的時候處理和查詢的時候處理哪種效率更高?
答:一類一行的在查詢的時候進行處理效率更高,原因是如果在索引的時候處理話要存儲的字段更多,並且在查詢的時候可擴展性更高,如果有新詞出現直接在同義詞文件里面增加新詞,然后重載即可。
標准化的方式在索引的時候處理的性能更高,原因是存儲的字段更少
練習1:自定義字段過濾停用詞和同義詞
步驟1:
在D:\solr-7.3.0\server\solr\mycore\conf目錄下的停用詞stopwords.txt和同義詞synonyms.txt的txt文件里面分別加入
停用詞:
hello
like
同義詞:
couch,sofa,divan
teh => the
huge,ginormous,humungous => large
small => tiny,teeny,weeny
步驟2:
在D:\solr-7.3.0\server\solr\mycore\conf目錄下的模式文件managed-schema里面自定義一個字段來進行分詞索引並配置停用詞和同義詞
<!--自定義字段過濾停用詞和同義詞 begin--> <fieldType name="myTestField" class="solr.SortableTextField" positionIncrementGap="100" multiValued="true"> <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> </fieldType> <!--自定義字段過濾停用詞和同義詞 end-->
步驟3:
重啟solr,在web控制台就可以進行測試查看效果了
練習2:在solr里面集成IKAnalyzer 中文分詞器
步驟1:
在原來學習lucene集成IKAnalyzer的基礎上,為IkAnalyzer實現一個TokenizerFactory(繼承它),接收useSmart參數。
步驟2:
將這三個類打成jar,如 IKAnalyzer-lucene7.3.jar
步驟3:
將這個IKAnalyzer-lucene7.3.jar和 IKAnalyzer的jar 拷貝到web應用的lib目錄下
步驟4:
將停用詞和擴展詞的三個配置文件拷貝到應用的classes目錄下
步驟5:
在schema中定義一個FieldType,使用IKAnalyzer適配類
<!--集成IK中文分詞器 里面有停用詞和擴展詞 begin--> <fieldType name="ik_zh_CN" class="solr.TextField"> <analyzer> <tokenizer class="com.study.lucene.demo.analizer.ik.IKTokenizer4Lucene7Factory" useSmart="true" /> </analyzer> </fieldType> <!--集成IK中文分詞器 里面有停用詞和擴展詞 end-->
步驟6.:
重啟solr,在web控制台就可以進行測試查看效果了
5. 時間字段類型
5.1 Solr中提供的時間字段類型( DatePointField-單個日期, DateRangeField-日期范圍,廢除的TrieDateField )是以時間毫秒數來存儲時間的。要求字段值以ISO-8601標准格式來表示時間:
YYYY-MM-DDThh:mm:ssZ
示例:
1999-05-20T17:33:18Z
Z表示是UTC時間(注意:就沒有時區了)
秒上可以帶小數來表示毫秒,超出精度(3位小數)部分會被忽略:
1972-05-20T17:33:18.772Z
1972-05-20T17:33:18.77Z
1972-05-20T17:33:18.7Z
公元前:在前面加減號 -
9999后,在前面加加號 +
注意:查詢時如果是直接的時間串,需要用轉移符轉義
datefield:1972-05-20T17\:33\:18.772Z
datefield:"1972-05-20T17:33:18.772Z"
datefield:[1972-05-20T17:33:18.772Z TO *]
5.2 DateRangeField 時間段類型特別說明
DateRangeField用來支持對時間段數據的索引,它遵守時間格式:YYYY-MM-DDThh:mm:ssZ,支持兩種時間段表示方式:
方式一:截斷日期,它表示整個日期跨度的精確指示。
2000-11 表示2000年11月整個月.
2000-11T13 表示2000年11月每天的13點這一個小時
-0009 公元前10年,0000是公元前1年。
方式二:范圍語法 [ TO ] { TO }
[2000-11-01 TO 2014-12-01] 日到日
[2014 TO 2014-12-01] 2014年開始到2014-12-01止.
[* TO 2014-12-01] 2014-12-01(含)前.
5.3 時間數學表達式
Solr中還支持用 NOW +- 時間的數學表達式來靈活表示時間。語法 NOW +- 帶單位的時間數,/單位 截斷。可用來表示時間段。
NOW+2MONTHS:現在的時間加上2個月
NOW-1DAY:現在的時間減去1天
NOW/HOUR:當前時間取整到小時
NOW+6MONTHS+3DAYS/DAY:當前時間+6個月+3天,然后取整到天
1972-05-20T17:33:18.772Z+6MONTHS+3DAYS/DAY
注意:運算順序是從左往右,只有加減取整運算,沒有乘除運算
NOW在查詢中使用時,可為NOW指定值:
q=solr&fq=start_date:[* TO NOW]&NOW=1384387200000
沒有&后面的賦值NOW就是當前時間
6. EnumFieldType 枚舉字段類別說明
EnumFieldType 用於字段值是一個枚舉集,且排序順序可預定的情況,如新聞分類這樣的字段。定義非常簡單:
<fieldType name="priorityLevel" class="solr.EnumFieldType" docValues="true" enumsConfig="enumsConfig.xml" enumName="priority"/>
說明:
enumsConfig:指定枚舉值的配置文件,絕對路徑或相對內核conf/的相對路徑
enumName:指定配置文件的枚舉名。排序順序是按配置的順序。
docValues : 枚舉類型字段必須設置 true;
枚舉配置示例:
<?xml version="1.0" ?> <enumsConfig> <enum name="priority"> <value>Not Available</value> <value>Low</value> <value>Medium</value> <value>High</value> <value>Urgent</value> </enum> <enum name="risk"> <value>Unknown</value> <value>Very Low</value> <value>Low</value> <value>Medium</value> <value>High</value> <value>Critical</value> </enum> </enumsConfig>
7. dynamic Field 動態字段
問:如果模式中有近百個字段需要定義,其中有很多字段的定義是相同,重復地定義是不是很煩?
可不可以定一個規則,字段名以某前綴開頭或結尾的是相同的定義配置,那這些重復字段就只需要配置一個,保證提交的字段名稱遵守這個前綴、后綴即可。 這就是動態字段。
如:整型字段都是一樣的定義,則可以定義一個動態字段如下:
<dynamicField name="*_i" type=“my_int" indexed="true" stored="true"/>
也可以是前綴,如 name=“i_*”
8. CopyField 復制字段
復制字段允許將一個或多個字段的值填充到一個字段中。它的用途有兩種:
1、將多個字段內容填充到一個字段,來進行搜索。如用戶輸入了多個搜索字段,程序就把這些字段放入一個字段里面進行搜索
2、對同一個字段內容進行不同的分詞過濾,創建一個新的可搜索字段
定義方式:
1、先定義一個普通字段
<field name="cc_all" type="zh_CN_text" indexed="true" stored="false" multiValued="false" />
2、定義復制字段
<copyField source="cat" dest="cc_all"/> <copyField source="name" dest="cc_all"/>
把cat和name這兩個字段都復制到cc_all這個字段里面
問:復制字段時,source可以是動態字段嗎?
答:可以
8. uniqueKey 唯一鍵
指定用作唯一鍵的字段,非必需。
<uniqueKey>id</uniqueKey>
唯一鍵字段不可以是保留字段、復制字段,且不能分詞。
注意:唯一鍵是業務的唯一字段,不是document的id
9. Similarity 相關性計算類配置
問:什么是相關性計算?
答:相關性計算指的是根據某個字段進行搜索時,把與搜索最匹配的排在前面
如果默認的相關性計算模型BM25Similarity不滿足你應用的特殊需要,你可在schema中指定全局的或字段類型局部的相關性計算類
示例:
<similarity class="solr.SchemaSimilarityFactory"> <str name="defaultSimFromFieldType">text_dfr</str> </similarity> <fieldType name="text_dfr" class="solr.TextField"> <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>
10. 小結:字段定義詳解
三、Schema API 介紹
前面我們都是采用自己在schema模式配置文件里面自己編寫配置文件的方式來定義模式,其實我們還可以使用schema API的方式來動態的定義模式,不用自己手工編寫配置文件,這樣更加方便
1、Schema操作API總體介紹
Solr中強烈推薦使用Schema API來管理集合/內核的模式信息,可以讀、寫模式信息。通過API來更新模式信息,solr將自動重載內核。但是請注意:模式修改並不會自動重索引已索引的文檔,只會對后續的文檔起作用,如果必要,你需要手動重索引(刪除原來的,重新提交文檔)。
1.1 更新Schema:
發送 post請求到 /collection/schema ,以JSON格式提交數據,在json中說明你要進行的更新操作及對應的數據(一次請求可進行多個操作)
1.2 更新操作定義
add-field: 添加一個新字段.
delete-field: 刪除一個字段.
replace-field: 替換一個字段,修改.
add-dynamic-field: 添加一個新動態字段.
delete-dynamic-field: 刪除一個動態字段
replace-dynamic-field: 替換一個已存在的動態字段
add-field-type: 添加一個fieldType.
delete-field-type: 刪除一個fieldType.
replace-field-type: 更新一個存在的fieldType
add-copy-field: 添加一個復制字段規則.
delete-copy-field: 刪除一個復制字段規則.
2、V1、V2兩個版本API說明
V1老版本的api,V2新版本的API,當前兩個版本的API都支持,將來會統一到新版本。兩個版本的API只是請求地址上的區別,參數沒區別。
V1: http://localhost:8983/solr/mycore/schema
V2: http://localhost:8983/api/cores/mycore/schema
說明:
mycore:solr里面定義的內核或者集合的名稱
3、FieldType字段類別操作
3.1 添加一個字段類別 add-field-type
使用postman來發送添加的請求:
請求地址:http://localhost:8983/solr/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"add-field-type": {
"name": "myNewTxtField",
"class": "solr.TextField",
"positionIncrementGap": "100",
"analyzer": {
"tokenizer": {
"class": "solr.WhitespaceTokenizerFactory"
},
"filters": [
{
"class": "solr.WordDelimiterFilterFactory",
"preserveOriginal": "0"
}
]
}
}
}
postman模擬請求:
在solr的web控制台查看添加的字段
添加字段時包含索引分析器和查詢分析器:
{
"add-field-type": {
"name": "myNewTextField",
"class": "solr.TextField",
"indexAnalyzer": {
"tokenizer": {
"class": "solr.PathHierarchyTokenizerFactory",
"delimiter": "/"
}
},
"queryAnalyzer": {
"tokenizer": {
"class": "solr.KeywordTokenizerFactory"
}
}
}
}
3.2 刪除一個字段類別 delete-field-type
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"delete-field-type": {
"name": "myNewTxtField"
}
}
3.3 替換一個字段類別 replace-field-type
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"replace-field-type": {
"name": "myNewTxtField",
"class": "solr.TextField",
"positionIncrementGap": "100",
"analyzer": {
"tokenizer": {
"class": "solr.StandardTokenizerFactory"
}
}
}
}
4、Field 字段操作
4.1 添加一個字段 add-field
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"add-field": {
"name": "sell_by",
"type": "myNewTxtField",
"stored": true
}
}
4.2 刪除一個字段 delete-field
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"delete-field": {
"name": "sell_by"
}
}
4.3 替換一個字段 replace-field
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"replace-field": {
"name": "sell_by",
"type": "date",
"stored": false
}
}
5、dynamicField 動態字段操作
5.1 添加一個動態字段 add-dynamic-field
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"add-dynamic-field": {
"name": "*_s",
"type": "string",
"stored": true
}
}
5.2 刪除一個動態字段 delete-dynamic-field
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"delete-dynamic-field": {
"name": "*_s"
}
}
5.3 替換一個動態字段 replace-dynamic-field
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"replace-dynamic-field":{
"name":"*_s",
"type":"text_general",
"stored":false }
}
6、copyField 復制字段操作
6.1 添加復制字段 add-copy-field
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"add-copy-field": {
"source": "shelf",
"dest": [
"location",
"catchall"
]
}
}
6.2 刪除復制字段 delete-copy-field
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"delete-copy-field": {
"source": "shelf",
"dest": "location"
}
}
7. 一次請求多個操作示例
7.1 同時添加字段類型和字段
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"add-field-type": {
"name": "myNewTxtField",
"class": "solr.TextField",
"positionIncrementGap": "100",
"analyzer": {
"tokenizer": {
"class": "solr.WhitespaceTokenizerFactory"
},
"filters": [
{
"class": "solr.WordDelimiterFilterFactory",
"preserveOriginal": "0"
}
]
}
},
"add-field": {
"name": "sell_by",
"type": "myNewTxtField",
"stored": true
}
}
7.2 一次添加多個字段
請求地址:http://localhost:8983/api/cores/mycore/schema
請求方式:post
設置頭信息為:Content-type:application/json
參數:json格式的參數
{
"add-field": [
{
"name": "shelf",
"type": "myNewTxtField",
"stored": true
},
{
"name": "location",
"type": "myNewTxtField",
"stored": true
}
]
}
8、獲取schema信息
8.1 獲取整個schema
GET /collection/schema
可以通過wt請求參數指定返回的格式:json,xml, schema.xml
http://localhost:8983/api/cores/mycore/schema?wt=xml
8.2 獲取字段
GET /collection/schema/fields
GET /collection/schema/fields/fieldname
請求參數有:
wt: json/xml fl:指定需要返回的字段名,以逗號或空格間隔
showDefaults:true/false ,是否返回字段的默認屬性
includeDynamic:true/false,在path中帶有fieldname 或指定了 fl的情況下才有用。
獲取所有字段:
http://localhost:8983/api/cores/mycore/schema/fields
獲取指定字段:
http://localhost:8983/api/cores/mycore/schema/fields/_root_
8.3 獲取動態字段
GET /collection/schema/dynamicfields
GET /collection/schema/dynamicfields/name
可用請求參數:wt、showDefaults
http://localhost:8983/api/cores/mycore/schema/dynamicfields?wt=xml
8.4 獲取字段類別
GET /collection/schema/fieldtypes
GET /collection/schema/fieldtypes/name
可用請求參數:wt、showDefaults
http://localhost:8983/api/cores/mycore/schema/fieldtypes?wt=xml
8.5 獲取復制字段
GET /collection/schema/copyfields
可用請求參數:wt、 source.fl、 dest.fl
8.6 獲取其他信息
GET /collection/schema/name 獲取schema的name
GET /collection/schema/version 獲取schema的版本
GET /collection/schema/uniquekey 獲取唯一鍵字段
GET /collection/schema/similarity 獲取全局相關性計算類
可用請求參數:wt