將文本拆解成標記只是工做的一半。爲了使這些標記更容易被搜索到,它們須要通過一個規範化的處理過程,以移除相同單詞間不重要的差別(好比:大小寫)。或許咱們還須要移除一些重要的差別,讓esta
、ésta
和 está
能夠做爲相同的詞被搜索。是會搜索 déjà vu
仍是 deja vu
呢?html
這是標記過濾器的工做,它從標記器接收一個標記流。咱們能夠有多個標記過濾器,他們各司其則,每一個都將它們前一個標記過濾器的輸出做爲本身的新標記流輸入。算法
elasticsearch版本: elasticsearch-2.xapp
使用最頻繁的標記過濾器要數 lowercase
小寫過濾器,正如咱們的指望,它將每一個標記轉換爲與之對應的小寫形式:less
GET /_analyze?tokenizer=standard&filters=lowercase The QUICK Brown FOX! #1
#1 輸出標記:the
、quick
、brown
、fox
elasticsearch
用戶是用 fox
仍是 FOX
並不重要,只要查詢時和搜索時使用的是同一套分析過程。lowercase
分析器會將查詢裏的 FOX
轉換成 fox
,它與咱們在倒排索引中存儲的標記一致。ide
將標記過濾器做爲分析過程的一部分來使用,咱們能夠建立一個自定義分析器:工具
PUT /my_index { "settings": { "analysis": { "analyzer": { "my_lowercaser": { "tokenizer": "standard", "filter": [ "lowercase" ] } } } } }
咱們能夠用 analyze
API 對其進行測試:測試
GET /my_index/_analyze?analyzer=my_lowercaser The QUICK Brown FOX! #1
#1 輸出標記 the
、quick
、brown
、fox
ui
英語只對舶來詞(如:rôle
、déjà
和 däis
)使用變音符號(´
、 ^
和 ¨
),但一般這不是必須的。其餘語言要求使用變音符以確保正確性。固然,即便由於索引中的詞都是拼寫正確的,也並不意味着用戶在搜索時也會使用正確的拼寫形式。this
將變音符從詞語中剔除一般會比較有用,讓 rôle
能夠匹配 role
,亦或反之。西方的語言能夠經過使用 asciifolding
字符過濾器來完成。實際上,它作的事情不僅是剔除變音符號,它試圖將許多 Unicode 字符轉換成更簡單的 ASCII 形式:
ß
⇒ ss
æ
⇒ ae
ł
⇒ l
ɰ
⇒ m
⁇
⇒ ??
❷
⇒ 2
⁶
⇒ 6
和 lowercase
過濾器同樣,asciifolding
過濾器無須任何配置,能夠被直接包括在一個自定義分析器中:
PUT /my_index { "settings": { "analysis": { "analyzer": { "folding": { "tokenizer": "standard", "filter": [ "lowercase", "asciifolding" ] } } } } } GET /my_index?analyzer=folding My œsophagus caused a débâcle #1
#1 輸出 my
、oesophagus
、caused
、a
、debacle
。
固然,在咱們剔除變音符號的時候,也會丟失詞語的意思。例如,考慮如下三個西班牙語的單詞:
esta
陰性形式的 this 形容詞,如:esta silla (this chair) 或 esta (this one)。(注:在西班牙語中,silla是陰性詞,esta作代詞時也代指陰性對象)。
ésta
esta
的舊式寫法。
está
第三人稱是動詞形式 estar
(to be,中文意思爲:是),如:está feliz
(he is happy,中文意思爲:他高興)。
但咱們會將前兩個形式合併,它們與第三個形式的意思是有區別的,咱們會將第三個形式獨立處理。相似:
sé
動詞 saber
的第一人稱形式(to know,中文意思爲:知道),如:Yo sé
(I know,中文意思爲:我知道).
se
第三人稱反身代詞,能夠與不少動詞聯用,如:se sabe
(it is known,中文意思爲:衆所周知)。
不幸的是,想要將應該剔除與不該剔除變音的詞區分開並不是易事。頗有多是連咱們用戶本身也都搞不清楚。
取而代之的是咱們對文本索引兩次:一次以原始形式,一次剔除變音形式:
PUT /my_index/_mapping/my_type { "properties": { "title": { #1 "type": "string", "analyzer": "standard", "fields": { "folded": { #2 "type": "string", "analyzer": "folding" } } } } }
#1 title
字段使用 standard
分析器,會包含原始單詞的變音形式。
#2 title.folded
字段使用 folding
分析器,會剔除變音符號。
用 analyze
API 對字段映射進行測試,測試的句子是 Esta está loca(This woman is crazy 這個女人瘋了):
GET /my_index/_analyze?field=title #1 Esta está loca GET /my_index/_analyze?field=title.folded #2 Esta está loca
#1 輸出 esta
、está
、loca
#2 輸出 esta
、esta
、loca
讓咱們索引一些供測試的文檔:
PUT /my_index/my_type/1 { "title": "Esta loca!" } PUT /my_index/my_type/2 { "title": "Está loca!" }
如今咱們可使用 multi_match
跨字段搜索,並在 most_fields
模式下合併每一個字段的評分結果:
GET /my_index/_search { "query": { "multi_match": { "type": "most_fields", "query": "esta loca", "fields": [ "title", "title.folded" ] } } }
用 validate-query
API 查看查詢的解釋工具:
GET /my_index/_validate/query?explain { "query": { "multi_match": { "type": "most_fields", "query": "está loca", "fields": [ "title", "title.folded" ] } } }
multi-match
查詢在 title
字段中搜索詞的原始形式(está),在 title.folded
中搜索詞的去變音形式(esta):
(title:está title:loca ) (title.folded:esta title.folded:loca)
用戶是在搜索 esta
仍是在搜索 está
並不重要,由於兩種形式分別同時存在於 title
和 title.folded
字段,兩個文檔都能被搜出。但在 title
字段中只存有原始形式,這個額外的匹配會使包含原始單詞的文檔處於結果列表的頂部。
咱們用 title.folded
字段來廣撒網,但願能匹配更多文檔,用原 title
字段將最相關的文檔推到結果列表的頂部。一樣的技術能夠在使用分析器時應用,經過犧牲詞語的含義來提高匹配的數量。
小貼士
asciifolding
過濾器確實有一個配置選項叫作preserve_original
讓咱們能夠將原始標記和經剔除的標記放在同一字段的同一位置。若是開啓這個配置選項,咱們會獲得以下結果:Position 1 Position 2 -------------------------- (ésta,esta) loca --------------------------儘管這看上去是一個節省空間的不錯方法,但這也意味着咱們無從要求過濾器對原始詞精確匹配。將原始標記和剔除變音的標記混在一塊兒還會影響到詞頻計數,進而致使相關度計算的可靠性會被弱化。
這裏有一個規則:將每一個字段及其變體分開索引。正如咱們在本部分裏作的同樣。
當 Elasticsearch 比較標記時,它是在字節級別處理這個問題的。換句話說,兩個被認爲相同的標記,需要由徹底相同的字節組成。但 Unicode 容許咱們用不一樣方式來表示同一個字符。
例如, é 和 é 之間有什麼區別?答案取決於問題的對象。在Elasticsearch裏,第一個由兩個字節組成0xC3
0xA9
,而第二個由三個字節組成 0x65
0xCC
0x81
。
在 Unicode 中,它們做爲字節如何表達的差別可有可無,它們是相同的字符,第一個是單個字符 é
,而第二個只是個 e
和重音符號 ´
的組合。
若是咱們獲取數據的來源不止一個,咱們可能會碰到相同的字符的不一樣編碼形式,這會致使一種形式的 déjà
沒法匹配一種。
幸運的是,咱們有現成的解決方案。Unicode 的規範化有四種形式,全部都是將 Unicode 字符轉換成標準格式,讓全部字符都能在字節層進行比較:nfc
、nfd
、nfkc
、nfkd
。
Unicode 規範化的形式(Unicode Normalization Forms)
整理型(
nfc
和nfkc
)以最少字節形式表示字符,因此é
是做爲單個字母表示的;分解型(nfd
和nfkd
)以字符的各自組成部分來表示,因此é
表示爲e
和´
。規範型(
nfc
和nfd
)以印刷形式表示字符,因此如ffi
或œ
是做爲單個字符表示的;兼容型(nfkc
和nfkd
)以拆解的簡單多字母形式表示字符,對應表示爲:f
+f
+i
和o
+e
。
咱們選擇何種規則形式並不十分重要,只要咱們全部的文本都是以相同形式表示的。這樣,相同的標記由相同的字節組成,也就是說,兼容模式容許咱們能夠將印刷形式(ffi
)與簡單字母表示(ffi
)相比較。
咱們能夠用 icu_normalizer
標記過濾器來確保全部的標記都是相同的形式:
PUT /my_index { "settings": { "analysis": { "filter": { "nfkc_normalizer": { #1 "type": "icu_normalizer", "name": "nfkc" } }, "analyzer": { "my_normalizer": { "tokenizer": "icu_tokenizer", "filter": [ "nfkc_normalizer" ] } } } } }
#1 將全部標記都規範化 nfkc
形式。
小貼士
除了前面提到的
icu_normalizer
標記過濾器,還有一個icu_normalizer
字符過濾器能夠作一樣的事情,但處理是發生在文本到達標記器以前。當使用standard
或icu_tokenizer
標記器的時候,這個差別不是十分重要。這些標記器都知道如何正確處理 Unicode 的全部形式。儘管如此,若是咱們打算使用不一樣的標記器,如:
ngram
、edge_ngram
或pattern
標記器,最好根據標記過濾器的偏好使用icu_normalizer
字符過濾器。
不少時候,咱們會想同時完成將其規範化和將其小寫的工做,能夠經過 icu_normalizer
來完成,使用自定義的規範化形式 nfkc_cf
,咱們將在下一部分中討論它。
若是沒喲發明才能人類什麼都不是,人類的語言正能體現這點。直處處理多語言時,都還認爲轉換一個詞的大小寫看似一個簡單的任務。
舉個例子,德語裏的小寫字母 ß
,轉換成大寫會是 SS
,再轉換回小寫是 ss
。或者考慮希臘語裏的字母 ς
(西格瑪,一般在詞的末尾使用),將其轉換成大寫會是 Σ
,再轉換回小寫是 σ
。
The whole point of lowercasing terms is to make them more likely to match, not less! In Unicode, this job is done by case folding rather than by lowercasing. Case folding is the act of converting words into a (usually lowercase) form that does not necessarily result in the correct spelling, but does allow case-insensitive comparisons.
將詞項小寫的目的是爲了讓它們更易於匹配,而不是更難!在 Unicode 中,這個工做經過大小寫轉換完成而不僅是小寫化。大小寫轉換是個將單詞轉換爲一種能夠不區分大小寫而能比較形式(一般是小寫形式)的動做,它並不要求結果裏拼寫的正確性。
例如,字母 ß
已是小寫了,經轉換成了 ss
。相似的,小寫 ς
經轉換變成 σ
,不管它們在單詞的什麼地方出現,都讓 σ
、ς
和 Σ
能夠相互比較。
icu_normalizer
標記過濾器使用的默認規範化形式是 nfkc_cf
,和 nfkc
形式同樣,它作下列事情:
ffi
變成 ffi
。它還會作下面事情:
換句話說,nfkc_cf
是 lowercase
小寫標記過濾器的等價形式,但它適於全部語言。on-steroids
與 standard
分析器等價:
PUT /my_index { "settings": { "analysis": { "analyzer": { "my_lowercaser": { "tokenizer": "icu_tokenizer", "filter": [ "icu_normalizer" ] #1 } } } } }
#1 icu_normalizer
默認使用 nfkc_cf
形式。
咱們能夠經過 standard
和 Unicode-aware
分析器運行比較 Weißkopfseeadler
和 WEISSKOPFSEEADLER
(等價的大寫形式)的結果:
GET /_analyze?analyzer=standard #1 Weißkopfseeadler WEISSKOPFSEEADLER GET /my_index/_analyze?analyzer=my_lowercaser #2 Weißkopfseeadler WEISSKOPFSEEADLER
#1 輸出標記 weißkopfseeadler
、weisskopfseeadler
#2 輸出標記 weisskopfseeadler
、weisskopfseeadler
standard
分析器輸出了兩個不一樣且不可比的標記,而咱們自定義的分析器輸出的標記是能夠比較的,無亂原始的形式如何。
一樣,使用 lowercase
標記過濾器對不少語言來講都是一個不錯的開始,但當被暴露在巴別塔下的時候,它的短處就會馬上突顯出來,asciifolding
標記過濾器要求與更有效的 Unicode 字符轉換 配合使用來應對多語言的世界。
icu_folding
標記過濾器(icu 插件內提供)與 asciifolding
過濾器作的事情同樣,但擴展了對不基於 ASCII 書寫形式的轉換支持,如:希臘語、希伯來語、漢語,將數字以它們等價的拉丁書寫形式表示,以及其餘各類數字、符號和標點的轉換。
icu_folding
標記過濾器自動應用 Unicode 規則化和 nfkc_cf
大小寫轉換方式,因此 icu_normalizer
不是必須的:
PUT /my_index { "settings": { "analysis": { "analyzer": { "my_folder": { "tokenizer": "icu_tokenizer", "filter": [ "icu_folding" ] } } } } } GET /my_index/_analyze?analyzer=my_folder ١٢٣٤٥ #1
#1 阿拉伯數字 ١٢٣٤٥
被轉換成了它們的拉丁等價形式:12345
。(注:一般咱們漢語中說的阿拉伯數字其實是拉丁數字)
若是須要對某些特殊字符禁止轉換,咱們能夠經過 UnicodeSet (很是像一個用正則式表示的一系列字符)來指定具體須要轉換的 Unicode 字符。例如,爲了排除瑞典語裏的字符 å
、ä
、ö
、Å
、Ä
和 Ö
, 咱們須要指定一個字符類來表示全部 Unicode 字符,除了字母:[^åäöÅÄÖ]
(^
表示排除)
PUT /my_index { "settings": { "analysis": { "filter": { "swedish_folding": { #1 "type": "icu_folding", "unicodeSetFilter": "[^åäöÅÄÖ]" } }, "analyzer": { "swedish_analyzer": { #2 "tokenizer": "icu_tokenizer", "filter": [ "swedish_folding", "lowercase" ] } } } } }
#1 swedish_folding
標記過濾自定義了 icu_folding
標記過濾器來排除全部瑞典語字母(同時排除大寫和小寫)。
#2 swedish
分析器先標記單詞,再用 swedish_folding
過濾器進行大小寫轉換,而後將每一個標記小寫以防它包括了某些應該被排除的大寫字母:Å
、Ä
或 Ö
。
本章到目前爲止,咱們介紹瞭如何對標記進行規範化處理。本章最後須要考慮的一個應用場景是字符串排序。
在 字符串排序和多字段(String Sorting and Multifields) 中,咱們解釋過 Elasticsearch 沒法對一個 analyzed
字符串字段進行排序,還展現說明如何使用 multifields 對同一字段創建多個索引,一個是 analyzed
字段供搜索使用,一個是 not_analyzed
字段供排序使用。
analyzed
字段的排序問題不在於它使用分析器,而在於分析器會將字符串標記成多個標記,就如同一袋子單詞,這使 Elasticsearch 不知道使用哪一個標記來排序。
依賴 not_analyzed
字段排序是不靈活的,它只容許咱們對原始字符串的精確值進行排序。可是,咱們 能夠 使用分析器來達到其餘方式排序的目的,只要咱們選擇的分析器爲每一個字符串始終輸出單個標記便可。
假設咱們有三個 user
文檔,它們的 name
字段分別包含:Boffey
、BROWN
和 bailey
。首先咱們應用在 字符串排序和多字段(String Sorting and Multifields) 裏描述的技術,用一個 not_analyzed
字段來排序:
PUT /my_index { "mappings": { "user": { "properties": { "name": { #1 "type": "string", "fields": { "raw": { #2 "type": "string", "index": "not_analyzed" } } } } } } }
#1 analyzed
name
字段是供搜索使用的。
#2 not_analyzed
name.raw
字段是供排序使用的。
咱們能夠索引一些文檔並嘗試排序:
PUT /my_index/user/1 { "name": "Boffey" } PUT /my_index/user/2 { "name": "BROWN" } PUT /my_index/user/3 { "name": "bailey" } GET /my_index/user/_search?sort=name.raw
前面的搜索請求會按如下順序返回文檔:BROWN
、Boffey
、bailey
。這是字典順序,與字母順序正好相反。實際上,用來表示大寫字母的字節值比用來表示小寫的要小,因此字節最小的排在最前。
這對計算機來講是合理的,可是對人類來講這卻不合常理,由於咱們但願名字是按字母順序排列的,無亂大小寫如何。爲了作到這點,須要對每一個名字的字節索引排序方式與咱們指望的順序一致。
換句話說,須要一個能輸出單個小寫形式的標記的分析器:
PUT /my_index { "settings": { "analysis": { "analyzer": { "case_insensitive_sort": { "tokenizer": "keyword", #1 "filter": [ "lowercase" ] #2 } } } } }
#1 keyword
標記器將原始未改變的字符串做爲單個標記輸出。
#2 lowercase
標記過濾器將標記以小寫形式輸出。
有了 case_insentive_sort
分析器,咱們能夠在 multifield
使用它:
PUT /my_index/_mapping/user { "properties": { "name": { "type": "string", "fields": { "lower_case_sort": { #1 "type": "string", "analyzer": "case_insensitive_sort" } } } } } PUT /my_index/user/1 { "name": "Boffey" } PUT /my_index/user/2 { "name": "BROWN" } PUT /my_index/user/3 { "name": "bailey" } GET /my_index/user/_search?sort=name.lower_case_sort
#1 name.lower_case_sort
字段爲咱們提供不區分大小寫的排序。
前面的搜索請求會按如下順序返回文檔:bailey
、Boffey
、BROWN
。
但這個順序正確嗎?這看上去是正確的是由於它正如咱們的指望同樣,可是咱們的指望頗有多是受了本書是用英語的並且示例文檔中全部字母都是英語字母。
若是咱們將德語名字 Böhm
加入結果會怎樣?
如今返回的名字順序會是:bailey
、Boffey
、BROWN
、Böhm
。Böhm
排在 BROWN
以後出現的緣由仍是因爲結果是按照表示詞的字節值來排序的,r
以字節 0x72
形式存儲,ö
以字節 0xF6
來存儲,因此排在最後。每一個字符的字節值是歷史偶然所形成的。
顯然,默認的排序方式除了適用英語,對其餘語言毫無心義,實際上,沒有「正確」的排序方式,只有適於語言的排序方式。
Every language has its own sort order, and sometimes even multiple sort orders. Here are a few examples of how our four names from the previous section would be sorted in different contexts:
每種語言都有它們本身的順序,有時甚至能夠有多種排序方式。這裏以咱們以前四個名字爲例,它們在不一樣的語境下有着不一樣的排序:
bailey
、boffey
、böhm
、brown
bailey
、boffey
、böhm
、brown
bailey
、böhm
、boffey
、brown
bailey
、boffey
、brown
、böhm
注意
之因此
böhm
排在boffey
以前是由於在德語電話簿中,當處理名字和地址時,ö
和oe
被認爲是同義詞,因此böhm
就像做爲boehm
排序同樣。
預約義排序是將文本按照預約順序進行排序的過程。Unicode Collation Algorithm 或 UCA (參見 www.unicode.org/reports/tr10) 定義了一個按照 排序元素表(Collation Element Table) 中預約義順序進行排序的方法。(一般 排序元素表 也被簡單稱爲 排序表(collation))
UCA 也定義了一個 默認 Unicode 排序元素表(Default Unicode Collation Element Table) 簡稱 DUCET,它爲全部的 Unicode 字符定義了默認的排序順序,與語言無關。正如咱們已經看到的,正確的排序順序並不惟一,因此 DUCET 的設計是爲了儘量減小用戶的煩惱,但它遠不足以在全部排序困境下都能成爲靈丹妙藥。
取而代之的是,由於世界上幾乎每種語言都有一個與語言相關的排序表,最通用的作法是先以 DUCET 做爲基準,再加入一些自定義規則來處理每種語言的獨特特性。
UCA 將字符串和排序表做爲輸入並輸出一個二進制排序鍵值,這樣讓字符串集合按照指定排序表來排序的過程就簡化成了比較它們的二進制鍵值。
小貼士
本部分描述的一些方法可能會在 Elasticsearch 的未來版本發生變化,最新的信息請參考 icu plugin 文檔。
icu_collation
標記過濾器默認使用 DUCET 排序規則進行排序,這是對默認排序的一個改進。要想使用它,咱們只須要建立一個使用默認 icu_collation
的分析器:
PUT /my_index { "settings": { "analysis": { "analyzer": { "ducet_sort": { "tokenizer": "keyword", "filter": [ "icu_collation" ] #1 } } } } }
#1 使用默認 DUCET 排序規則。
通常來講,咱們想要排序的字段一樣也是咱們想要搜索的字段,因此咱們使用與 無大小寫區分的排序(Case-Insensitive Sorting) 中相同的 multifield 方法:
PUT /my_index/_mapping/user { "properties": { "name": { "type": "string", "fields": { "sort": { "type": "string", "analyzer": "ducet_sort" } } } } }
有了這個映射, the name.sort
字段會包含一個排序鍵值僅供排序時使用。咱們沒有指定任何語言,因此它默認使用 DUCET 排序規則。
如今咱們對示例中的文檔從新索引再測試排序:
PUT /my_index/user/_bulk { "index": { "_id": 1 }} { "name": "Boffey" } { "index": { "_id": 2 }} { "name": "BROWN" } { "index": { "_id": 3 }} { "name": "bailey" } { "index": { "_id": 4 }} { "name": "Böhm" } GET /my_index/user/_search?sort=name.sort
注意
注意排序鍵值與每一個文檔一塊兒返回,因此以前例子中的
brown
和böhm
會看上去使人費解:ᖔ乏昫တ倈⠀\u0001
。緣由是icu_collation
過濾器輸出的鍵值只是爲了排序的高效,而沒有其餘任何目的。
前面搜索返回文檔的順序是:bailey
、Boffey
、Böhm
、BROWN
。這已是一個進步了,由於如今的順序對於英語和德語來講都是對的,但對於德語電話簿和瑞典語來講仍是不正確。下一步要作的是對不一樣語言自定義咱們的映射。
icu_collation
過濾器能夠爲特定語言配置不一樣的排序表,不管是一個國家的語言,仍是其餘某些語言的子集(如:德語電話簿)。這能夠經過建立一個自定義版本的標記過濾器並使用參數 language
、country
和variant
來作到:
英語(English)
{ "language": "en" }
德語(German)
{ "language": "de" }
奧地利德語(Austrian German)
{ "language": "de", "country": "AT" }
德語電話簿(German phonebooks)
{ "language": "de", "variant": "@collation=phonebook" }
小貼士
更多關於地域支持的信息,請參見:http://userguide.icu-project.org/locale。
這個示例爲咱們展現瞭如何給德語電話簿設置排序順序:
PUT /my_index { "settings": { "number_of_shards": 1, "analysis": { "filter": { "german_phonebook": { #1 "type": "icu_collation", "language": "de", "country": "DE", "variant": "@collation=phonebook" } }, "analyzer": { "german_phonebook": { #2 "tokenizer": "keyword", "filter": [ "german_phonebook" ] } } } }, "mappings": { "user": { "properties": { "name": { "type": "string", "fields": { "sort": { #3 "type": "string", "analyzer": "german_phonebook" } } } } } } }
#1 首先咱們爲德語電話簿建立一個自定義的 icu_collation
。
#2 而後將其包在一個自定義分析器中。
#3 最後在 name.sort
字段應用。
從新索引數據再次執行前面的搜索:
PUT /my_index/user/_bulk { "index": { "_id": 1 }} { "name": "Boffey" } { "index": { "_id": 2 }} { "name": "BROWN" } { "index": { "_id": 3 }} { "name": "bailey" } { "index": { "_id": 4 }} { "name": "Böhm" } GET /my_index/user/_search?sort=name.sort
如今返回文檔的順序是:bailey
、Böhm
、Boffey
、BROWN
。在德語電話簿中,Böhm
與 Boehm
是等價的,因此它應該出如今 Boffey
以前。
相同的字段也能夠支持多個排序順序,只要爲每種語言使用 multifield 就能作到:
PUT /my_index/_mapping/_user { "properties": { "name": { "type": "string", "fields": { "default": { "type": "string", "analyzer": "ducet" #1 }, "french": { "type": "string", "analyzer": "french" #2 }, "german": { "type": "string", "analyzer": "german_phonebook" #3 }, "swedish": { "type": "string", "analyzer": "swedish" #4 } } } } }
#1 #2 #3 #4 咱們須要爲每一個排序規則建立相應的分析器。
有了這個映射,結果的順序對於法語、德語和瑞典語的用戶都是正確的,只需根據字段 name.french
、 name.german
或 name.swedish
排序便可。對於不支持的語言會根據默認字段 name.default
使用 DUCET 排序規則。
icu_collation
標記過濾器除了 language
、country
和 variant
還有其餘不少配置選項,它們均可以被用以對排序算法進行裁剪。這些選項能夠提供如下功能:
這些配置選項的詳細使用方法超出本書的範圍,更多的內容能夠在 ICU plug-in 文檔 和 ICU project collation 文檔 中找到。