在solr中有很多關(guān)于字段和字段類型屬性,這些屬性非常重要室埋,直接決定了我們對solr的理解深度嗽上,我一直對這些概念有些模糊次舌,有必要總結(jié)下,給自己也給別人留個(gè)記錄吧兽愤。
本文說鎖的屬性彼念,均是指schemal格式定義文件(以前默認(rèn)叫schema.xml挪圾,6.0版本以后默認(rèn)是managed-schema )中定義的屬性。
一.關(guān)于字段定義屬性
1.Indexed和Stored
在字段的屬性中最常見的就是這兩個(gè)屬性了逐沙,如:
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
Indexed
簡單說明: 索引的字段是在搜索的時(shí)候可以用它來查詢或排序哲思,在lucene中,被索引的字段將會建立倒排表.
Stored
簡單說明: 一個(gè)字段是否被存儲吩案,取決于你是否想在solr的查詢結(jié)果中得到它棚赔,也就是說你是否想在查詢結(jié)果中看到它,它將會消耗cpu和io和磁盤空間等資源徘郭。
2.multiValued
設(shè)置為true表示此字段可以存儲多個(gè)值靠益,意思是這個(gè)字段在一個(gè)文檔中可以存儲多個(gè)值的內(nèi)容。
如:
<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
3.required
提示solr拒絕添加沒有這個(gè)字段的任何文檔崎岂,默認(rèn)這個(gè)值設(shè)置為假捆毫。
簡單來說就是這個(gè)字段是必須的,類似數(shù)據(jù)庫的非空冲甘,如果添加的文檔字段為空,則添加不到索引上去途样。
如:
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
如果添加的文檔缺少這id字段就報(bào)錯(cuò)江醇。
<uniqueKey>id</uniqueKey> 表示定義id字段為唯一值字段,這可以防止重復(fù)建索引何暇,另外在Solr的云模式部署下是必須設(shè)置的陶夜,最好用string或long等基礎(chǔ)數(shù)據(jù)類型作為唯一字段。
4.type
字段的類型裆站,定義了字段的存儲和處理方式条辟,如string類型標(biāo)示字段值將會被原樣存儲,不分詞籍救,不改變况凉。
5.default
字段的默認(rèn)值芦鳍,經(jīng)常用在字段是必須的,但是有時(shí)候又無法提供的情況杭棵,solr就會用默認(rèn)值替代。如:
<field name="recordTime" type="date" indexed="true" stored="true" required="true" default="NOW+8HOUR"/>
標(biāo)示recordTime如果沒有提供氛赐,用當(dāng)前的時(shí)間+8個(gè)小時(shí)作為recordTime的時(shí)間魂爪,加8小時(shí)是因?yàn)閟olr默認(rèn)時(shí)區(qū)是0時(shí)區(qū),按照中國北京時(shí)間(東8區(qū))算艰管,需要加上8個(gè)小時(shí)滓侍。
二.類型高級屬性
1.docValue
在solr的schema定義中,基本的long牲芋、int撩笆、double尔破、float類型設(shè)置docValue,如下:
<fieldType name="long" class="solr.TrieLongField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
當(dāng)然也可以在字段里面直接定義:
<field name="_root_" type="string" indexed="true" stored="false" docValues="false" />
solr說明:
如果此字段應(yīng)包含doc值浇衬,則為true懒构。 Doc值為用于分面(faceting),分組耘擂,排序和函數(shù)查詢胆剧。 雖然不是required,doc值會使索引加載更快醉冤,更多 NRT友好和更高內(nèi)存利用率秩霍。
但他們有一些 限制:它們目前只受StrField,UUIDField支持 和所有Trie *字段蚁阳,并且根據(jù)字段類型铃绒,它們可能要求字段為單值,是必需的或具有默認(rèn)值 螺捐。
docValue值存在正排索引中颠悬,只所以在排序的時(shí)候效果更好,是因?yàn)閐ocValue是按照列存儲的定血,又存在正排索引中赔癌,所以可以通過文檔ID快速找到它。
說明下: lucene的倒排索引是:Term(詞)-> 文檔ID
這樣根據(jù)類似Hash算法澜沟,通過詞可以迅速找到文檔ID灾票,然后把相關(guān)字段取處理。但是也有不利的方面就是如果要進(jìn)行分組或排序的時(shí)候茫虽,會遍歷取出所有文檔的字段刊苍,然后在內(nèi)存中根據(jù)排序字段進(jìn)行排序,非常耗時(shí)和占用內(nèi)存濒析。
設(shè)置docValue就構(gòu)建了正排索引正什,即文檔ID->docValue字段,而且docValue字段又是排好序的悼枢,按照列存儲的埠忘。只是簡單說明。
設(shè)置docValue在lucene其實(shí)是增加一個(gè)字段馒索,所以占存儲莹妒,影響建索引效率。
useDocValuesAsStored:如果這一項(xiàng)設(shè)置為true則標(biāo)示所有docValue為true的字段將被存儲绰上,即使它的stored=false旨怠。
2.omitNorms
solr對這個(gè)屬性解釋的有點(diǎn)拗口,自己理解下蜈块,就是如果這個(gè)為true鉴腻,則在索引中不存在這個(gè)字段的長度屬性迷扇。這在給文檔打分的時(shí)候用的到。
舉個(gè)例子爽哎,一個(gè)詞語蜓席,在兩篇文章中,一般認(rèn)為段的文章比長的文章是不是要更加符合查詢的需要(因?yàn)檫@個(gè)詞在兩篇文章中權(quán)重不一樣课锌,比如在100個(gè)詞的文章中厨内,這個(gè)詞權(quán)重為0.01; 在100個(gè)詞的文章中渺贤,這個(gè)詞權(quán)重為0.001)雏胃,如果是,則需要用長度來加強(qiáng)文檔打分的策略志鞍,這就是這個(gè)屬性的作用瞭亮。Norm 在Lucene中是按照浮點(diǎn)數(shù)的形式,只占用一個(gè)字節(jié)的方式存儲的固棚。
忽略情況:
1统翩、如果你的doc的字段的內(nèi)容長度大小比較一致,則可以忽略玻孟。
2唆缴、如果在查詢結(jié)果中,字段內(nèi)容的長度對你的結(jié)果匹配無影響忽略黍翎。
3、需要節(jié)省空間艳丛,提高建索引和查詢的性能匣掸。
使用情況:
1、字段內(nèi)容長度影響了文檔的打分氮双,則需要使用碰酝。
在solr中,默認(rèn)的時(shí)間戴差、string或數(shù)字類型送爸,這個(gè)屬性為true。
3.termVectors
在solr中暖释,我們通過查詢的內(nèi)容的詞向量和文檔中的此向量之間的夾角來求相關(guān)性袭厂,給文檔相關(guān)性打分(詞向量比較復(fù)雜,回頭單獨(dú)寫一篇文章來闡述)球匕。
solr中有個(gè)MoreLikeThis 的功能纹磺,現(xiàn)在很多電商的查詢里面的找類似就是這個(gè)功能,solr利用term Vectors來計(jì)算相關(guān)度亮曹,通常是是利用存儲在索引中查詢信息計(jì)算的橄杨,設(shè)置termVectors為true秘症,則可以在建索引的時(shí)候計(jì)算term Vector信息,且保存在索引中式矫。
這對大數(shù)據(jù)量的索引來說乡摹,影響很大。如果你重度使用MoreLikeThis 的功能采转,可以開啟這個(gè)屬性聪廉。
4.termPositions和termOffset、termPayLoads
這三項(xiàng)和前面的termVectors關(guān)系很大氏义,是在前面一項(xiàng)為true的情況下锄列,這三項(xiàng)才有效果。分別是指詞在文檔中所處位置惯悠、詞的偏移量邻邮、詞在詞向量中比重信息(詞在文章中重要性?不確定此處)克婶。
可以加速高亮功能和其他輔助功能筒严,當(dāng)然如果設(shè)置為true也會增加索引的大小和降低建索引的速度。
omitTermFreqAndPositions:
如果設(shè)置為true情萤,則忽略詞出現(xiàn)的頻次鸭蛙、位置和在文章中這個(gè)字段的比重信息。在不需要這些信息時(shí)候可以改進(jìn)索引性能筋岛。減少索引的大小娶视。依賴這個(gè)詞的位置的查詢將默默地顯示找不到信息,除了textField字段類型睁宰,其他字段類型默認(rèn)設(shè)置為true肪获。
omitPositions : 和omitTermFreqAndPositions 類似僅僅忽略位置。
5.precisionStep 和positionIncrementGap
precisionStep
這可能是這幾個(gè)屬性里面最難理解的屬性了柒傻,不過這個(gè)屬性用在數(shù)字或時(shí)間字段的范圍查詢或者排序的時(shí)候孝赫。通過字面理解就是精度步長,簡單來說就是通過保存數(shù)據(jù)的多個(gè)精度來加快數(shù)據(jù)的范圍定位红符。
舉個(gè)例子青柄,比如你在電商網(wǎng)站查詢價(jià)格范圍在1000 到10000之間的所有手機(jī),這里面就用到了范圍搜索预侯。如果價(jià)格值的范圍很小致开,用precisionStep 沒多大意義,只有大量數(shù)據(jù)的時(shí)候使用它才可能起到加快搜索的作用雌桑。
假設(shè)手機(jī)價(jià)格如下定義:
<field name="phone_price" type="tint" indexed="true" stored="true" /
和
<fieldType name="tint" class="solr.TrieIntField"precisionStep="8"positionIncrementGap="0"/>
首先說明在solr中(在lucene中)喇喉,一個(gè)數(shù)字類型(Date類型實(shí)際是按照Long來存儲的)最高精度是其本身,這也稱為基數(shù)據(jù)校坑。
solr對于一個(gè)具有precisionStep非0的值保存了多個(gè)不同精度的term拣技。
按照Solr In Action舉例如圖:
tint四個(gè)字節(jié)千诬,按照precisionStep=8 ,則說明精度按照8位切分膏斤,4個(gè)字節(jié)一共32位徐绑,剛好保存四個(gè)值。
通過這兩個(gè)圖的對比莫辨,更小的步長傲茄,則同一個(gè)值需要保存更多的term,
當(dāng)然范圍搜索也更加精確沮榜,查找速度更快盘榨,但是也同樣會增大索引的大小。
同樣是50000個(gè)價(jià)格隨機(jī)數(shù)蟆融,在不同的precisionStep下的索引大小和范圍查詢速度的快慢草巡。
positionIncrementGap
它是和multiValued一起使用的,標(biāo)示多值之間虛擬空白的數(shù)量型酥。
舉個(gè)網(wǎng)上的例子:
title1: ab cd
title2: xy zz
如果positionIncrementGap=0山憨,那么這四個(gè)term的位置為0,1,2,3。如果檢索"cd xy"那么能夠找到弥喉,如果你不想讓它找到郁竟,那么就需要調(diào)整positionIncrementGap值。如100由境,那么這是位置為0,1,100,101棚亩。這樣就不能匹配了。
6.sortMissingFirst 和sortMissingLast
這兩個(gè)比較好理解虏杰,是文檔在排序的時(shí)候蔑舞,如果排序字段的值缺失,那么是排在前面還是排在后面嘹屯。
參考資料
1.Solr In Action(非常棒的一本書,學(xué)習(xí)solr的必看)
2.apache-solr-ref-guide-6.0.pdf