全文檢索引擎 Solr 部署與基本原理
-
搜索引擎Solr環境搭建實例
-
關於 solr , schema.xml 的配置說明
-
全文檢索引擎Solr系列—–全文檢索基本原理
一、搜索引擎Solr環境搭建實例
Solr服務器采用java5開發的,是基於Lucene全文搜索的。要想搭建Solr,首先進行java環境的配置,安裝對應的jdk以及tomcat,在此就不多講。
以下是在jdk1.7和tomcat1.7的環境下搭建最新版本的solr4.10.3。
具體步驟如下:
1.到官網http://lucene.apache.org/solr/mirrors-solr-latest-redir.html下載.
2.建目錄/webapps/mysolr/solr
3.解壓壓縮包solr-4.10.3,找到example下的webapps中的solr.war包,並將其解壓。
4.將解壓完的war包(solr文件夾)拷貝到第2步建的目錄:/webapps/mysolr下
5.拷貝兩個地方的jar包到/webapps/mysolr/solr/WEB-INF/lib下
(1)example下lib包的所有jar包
(2)example下lib包下的ext包中的所有jar包
6.拷貝example/resource下的log4j.properties文件到/webapps/mysolr/solr/classpath 下
7.solrhome的配置:
先創建一個solrhome目錄:/webapps/mysolr/solrhome,然后將example/solr下的所有文件拷貝到/webapps/mysolr/solrhome下
然后修改配置文件/webapps/mysolr/solr/WEB-INF/web.xml,將solr/home的注解放開並配置如下:
<env-entry> <env-entry-name>solr/home</env-entry-name> <env-entry-value>/webapps/mysolr/solrhome</env-entry-value> <env-entry-type>java.lang.String</env-entry-type> </env-entry>
8.把/webapps/mysolr/solr部署到tomcat下,並啟動tomcat。
以上就完成了solr環境的基本搭建,訪問http://loclhost:8080/solr 可看到如下界面:

Solr3.6.1 在Tomcat6下的環境搭建 http://www.cnblogs.com/chinway/p/6187260.html
基於Tomcat的Solr3.5集群部署 http://www.cnblogs.com/chinway/p/6187271.html
在Linux上使用Nginx為Solr集群做負載均衡 http://www.cnblogs.com/chinway/p/6187292.html
Linux下安裝使用Solr http://www.cnblogs.com/chinway/p/6187322.html
Solr實現Low Level查詢解析(QParser) http://www.cnblogs.com/chinway/p/6187332.html
Solr 4.0 部署實例教程 http://www.cnblogs.com/chinway/p/6187382.html
二、 關於 solr , schema.xml 的配置說明
schema.xml位於solr/conf/目錄下,類似於數據表配置文件,
定義了加入索引的數據的數據類型,主要包括type、fields和其他的一些缺省設置。
1、先來看下type節點,這里面定義FieldType子節點,包括name,class,positionIncrementGap等一些參數。
- name:就是這個FieldType的名稱。
- class:指向org.apache.solr.analysis包里面對應的class名稱,用來定義這個類型的行為。
1 < schema name = "example" version = "1.2" > 2 < types > 3 < fieldType name = "string" class = "solr.StrField" sortMissingLast = "true" omitNorms = "true" /> 4 < fieldType name = "boolean" class = "solr.BoolField" sortMissingLast = "true" omitNorms = "true" /> 5 < fieldtype name = "binary" class = "solr.BinaryField" /> 6 < fieldType name = "int" class = "solr.TrieIntField" precisionStep = "0" omitNorms = "true" 7 positionIncrementGap = "0" /> 8 < fieldType name = "float" class = "solr.TrieFloatField" precisionStep = "0" omitNorms = "true" 9 positionIncrementGap = "0" /> 10 < fieldType name = "long" class = "solr.TrieLongField" precisionStep = "0" omitNorms = "true" 11 positionIncrementGap = "0" /> 12 < fieldType name = "double" class = "solr.TrieDoubleField" precisionStep = "0" omitNorms = "true" 13 positionIncrementGap = "0" /> 14 ... 15 </ types > 16 ... 17 </ schema >
必要的時候fieldType還需要自己定義這個類型的數據在建立索引和進行查詢的時候要使用的分析器analyzer,包括分詞和過濾,如下:
1 < fieldType name = "text_ws" class = "solr.TextField" positionIncrementGap = "100" > 2 < analyzer > 3 < tokenizer class = "solr.WhitespaceTokenizerFactory" /> 4 </ analyzer > 5 </ fieldType > 6 < fieldType name = "text" class = "solr.TextField" positionIncrementGap = "100" > 7 < analyzer type = "index" > 8 <!--這個分詞包是空格分詞,在向索引庫添加text類型的索引時,Solr會首先用空格進行分詞 9 然后把分詞結果依次使用指定的過濾器進行過濾,最后剩下的結果,才會加入到索引庫中以備查詢。 10 注意:Solr的analysis包並沒有帶支持中文的包,需要自己添加中文分詞器,google下。 11 --> 12 < tokenizer class = "solr.WhitespaceTokenizerFactory" /> 13 <!-- in this example, we will only use synonyms at query time 14 < filter class = "solr.SynonymFilterFactory" synonyms = "index_synonyms.txt" 15 ignoreCase = "true" expand = "false" /> 16 --> 17 <!-- Case insensitive stop word removal. 18 add enablePositionIncrements = true in both the index and query 19 analyzers to leave a 'gap' for more accurate phrase queries. 20 --> 21 < filter class = "solr.StopFilterFactory" 22 ignoreCase = "true" 23 words = "stopwords.txt" 24 enablePositionIncrements = "true" 25 /> 26 < filter class = "solr.WordDelimiterFilterFactory" generateWordParts = "1" 27 generateNumberParts = "1" catenateWords = "1" catenateNumbers = "1" 28 catenateAll = "0" splitOnCaseChange = "1" /> 29 < filter class = "solr.LowerCaseFilterFactory" /> 30 < filter class = "solr.SnowballPorterFilterFactory" language = "English" 31 protected = "protwords.txt" /> 32 </ analyzer > 33 < analyzer type = "query" > 34 < tokenizer class = "solr.WhitespaceTokenizerFactory" /> 35 < filter class = "solr.SynonymFilterFactory" synonyms = "synonyms.txt" ignoreCase = "true" 36 expand = "true" /> 37 < filter class = "solr.StopFilterFactory" 38 ignoreCase = "true" 39 words = "stopwords.txt" 40 enablePositionIncrements = "true" 41 /> 42 < filter class = "solr.WordDelimiterFilterFactory" generateWordParts = "1" 43 generateNumberParts = "1" catenateWords = "0" catenateNumbers = "0" 44 catenateAll = "0" splitOnCaseChange = "1" /> 45 < filter class = "solr.LowerCaseFilterFactory" /> 46 < filter class = "solr.SnowballPorterFilterFactory" language = "English" 47 protected = "protwords.txt" /> 48 </ analyzer > 49 </ fieldType >
2、再來看下fields節點內定義具體的字段(類似數據庫的字段),含有以下屬性:
- name:字段名
- type:之前定義過的各種FieldType
- indexed:是否被索引
- stored:是否被存儲(如果不需要存儲相應字段值,盡量設為false)
- multiValued:是否有多個值(對可能存在多值的字段盡量設置為true,避免建索引時拋出錯誤)
1 < fields > 2 < field name = "id" type = "integer" indexed = "true" stored = "true" required = "true" /> 3 < field name = "name" type = "text" indexed = "true" stored = "true" /> 4 < field name = "summary" type = "text" indexed = "true" stored = "true" /> 5 < field name = "author" type = "string" indexed = "true" stored = "true" /> 6 < field name = "date" type = "date" indexed = "false" stored = "true" /> 7 < field name = "content" type = "text" indexed = "true" stored = "false" /> 8 < field name = "keywords" type = "keyword_text" indexed = "true" stored = "false" multiValued = "true" /> 9 <!--拷貝字段--> 10 < field name = "all" type = "text" indexed = "true" stored = "false" multiValued = "true" /> 11 </ fields >
3、建議建立一個拷貝字段,將所有的 全文本 字段復制到一個字段中,以便進行統一的檢索:
以下是拷貝設置:
1 < copyField source = "name" dest = "all" /> 2 < copyField source = "summary" dest = "all" />
4、動態字段,沒有具體名稱的字段,用dynamicField字段
如:name為*_i,定義它的type為int,那么在使用這個字段的時候,任務以_i結果的字段都被認為符合這個定義。如name_i, school_i
1 < dynamicField name = "*_i" type = "int" indexed = "true" stored = "true" /> 2 < dynamicField name = "*_s" type = "string" indexed = "true" stored = "true" /> 3 < dynamicField name = "*_l" type = "long" indexed = "true" stored = "true" /> 4 < dynamicField name = "*_t" type = "text" indexed = "true" stored = "true" /> 5 < dynamicField name = "*_b" type = "boolean" indexed = "true" stored = "true" /> 6 < dynamicField name = "*_f" type = "float" indexed = "true" stored = "true" /> 7 < dynamicField name = "*_d" type = "double" indexed = "true" stored = "true" /> 8 < dynamicField name = "*_dt" type = "date" indexed = "true" stored = "true" />
schema.xml文檔注釋中的信息:
1、為了改進性能,可以采取以下幾種措施:
- 將所有只用於搜索的,而不需要作為結果的field(特別是一些比較大的field)的stored設置為false
- 將不需要被用於搜索的,而只是作為結果返回的field的indexed設置為false
- 刪除所有不必要的copyField聲明
- 為了索引字段的最小化和搜索的效率,將所有的 text fields的index都設置成field,然后使用copyField將他們都復制到一個總的 text field上,然后對他進行搜索。
- 為了最大化搜索效率,使用java編寫的客戶端與solr交互(使用流通信)
- 在服務器端運行JVM(省去網絡通信),使用盡可能高的Log輸出等級,減少日志量。
2、< schema name =" example " version =" 1.2 " >
- name:標識這個schema的名字
- version:現在版本是1.2
3、filedType
1 < fieldType name =" string " class =" solr.StrField " sortMissingLast =" true " omitNorms =" true " />
- name:標識而已。
- class和其他屬性決定了這個fieldType的實際行為。(class以solr開始的,都是在org.appache.solr.analysis包下)
可選的屬性:
- sortMissingLast和sortMissingFirst兩個屬性是用在可以內在使用String排序的類型上(包括:string,boolean,sint,slong,sfloat,sdouble,pdate)。
- sortMissingLast="true",沒有該field的數據排在有該field的數據之后,而不管請求時的排序規則。
- sortMissingFirst="true",跟上面倒過來唄。
- 2個值默認是設置成false
StrField類型不被分析,而是被逐字地索引/存儲。
StrField和TextField都有一個可選的屬性“compressThreshold”,保證壓縮到不小於一個大小(單位:char)
1 < fieldType name =" text " class =" solr.TextField " positionIncrementGap =" 100 " >
solr.TextField 允許用戶通過分析器來定制索引和查詢,分析器包括一個分詞器(tokenizer)和多個過濾器(filter)
- positionIncrementGap:可選屬性,定義在同一個文檔中此類型數據的空白間隔,避免短語匹配錯誤。
name: 字段類型名
class: java類名
indexed: 缺省true。 說明這個數據應被搜索和排序,如果數據沒有indexed,則stored應是true。
stored: 缺省true。說明這個字段被包含在搜索結果中是合適的。如果數據沒有stored,則indexed應是true。
sortMissingLast: 指沒有該指定字段數據的document排在有該指定字段數據的document的后面
sortMissingFirst: 指沒有該指定字段數據的document排在有該指定字段數據的document的前面
omitNorms: 字段的長度不影響得分和在索引時不做boost時,設置它為true。一般文本字段不設置為true。
termVectors: 如果字段被用來做more like this 和highlight的特性時應設置為true。
compressed: 字段是壓縮的。這可能導致索引和搜索變慢,但會減少存儲空間,只有StrField和TextField是可以壓縮,這通常適合字段的長度超過200個字符。
multiValued: 字段多於一個值的時候,可設置為true。
positionIncrementGap: 和multiValued
一起使用,設置多個值之間的虛擬空白的數量
1 < tokenizer class =" solr.WhitespaceTokenizerFactory " />
空格分詞,精確匹配。
1 < filter class =" solr.WordDelimiterFilterFactory " generateWordParts =" 1 " generateNumberParts =" 1 " catenateWords =" 1 " catenateNumbers =" 1 " catenateAll =" 0 " splitOnCaseChange =" 1 " />
在分詞和匹配時,考慮 "-"連字符,字母數字的界限,非字母數字字符,這樣 "wifi"或"wi fi"都能匹配"Wi-Fi"。
1 < filter class =" solr.SynonymFilterFactory " synonyms =" synonyms.txt " ignoreCase =" true " expand =" true " />
同義詞
1 < filter class =" solr.StopFilterFactory " ignoreCase =" true " words =" stopwords.txt " enablePositionIncrements =" true " />
在禁用字(stopword)刪除后,在短語間增加間隔
stopword:即在建立索引過程中(建立索引和搜索)被忽略的詞,比如is this等常用詞。在conf/stopwords.txt維護。
4、fields
1 < field name =" id " type =" string " indexed =" true " stored =" true " required =" true " />
- name:標識而已。
- type:先前定義的類型。
- indexed:是否被用來建立索引(關系到搜索和排序)
- stored:是否儲存
- compressed:[false],是否使用gzip壓縮(只有TextField和StrField可以壓縮)
- mutiValued:是否包含多個值
- omitNorms:是否忽略掉Norm,可以節省內存空間,只有全文本field和need an index-time boost的field需要norm。(具體沒看懂,注釋里有矛盾)
- termVectors:[false],當設置true,會存儲 term vector。當使用MoreLikeThis,用來作為相似詞的field應該存儲起來。
- termPositions:存儲 term vector中的地址信息,會消耗存儲開銷。
- termOffsets:存儲 term vector 的偏移量,會消耗存儲開銷。
- default:如果沒有屬性需要修改,就可以用這個標識下。
< field name =" text " type =" text " indexed =" true " stored =" false " multiValued =" true " />
包羅萬象(有點誇張)的field,包含所有可搜索的text fields,通過copyField實現。
< copyField source =" cat " dest =" text " />
在添加索引時,將所有被拷貝field(如cat)中的數據拷貝到text field中
作用:
- 將多個field的數據放在一起同時搜索,提供速度
- 將一個field的數據拷貝到另一個,可以用2種不同的方式來建立索引。
< dynamicField name =" *_i " type =" int " indexed =" true " stored =" true " />
如果一個field的名字沒有匹配到,那么就會用動態field試圖匹配定義的各種模式。
- "*"只能出現在模式的最前和最后
- 較長的模式會被先去做匹配
- 如果2個模式同時匹配上,最先定義的優先
1 < dynamicField name =" * " type =" ignored " multiValued=" true " />
如果通過上面的匹配都沒找到,可以定義這個,然后定義個type,當String處理。(一般不會發生)
但若不定義,找不到匹配會報錯。
5、其他一些標簽
1 < uniqueKey > id </ uniqueKey >
文檔的唯一標識, 必須填寫這個field(除非該field被標記required="false"),否則solr建立索引報錯。
< defaultSearchField > text </ defaultSearchField >
如果搜索參數中沒有指定具體的field,那么這是默認的域。
1 < solrQueryParser defaultOperator =" OR " />
配置搜索參數短語間的邏輯,可以是"AND|OR"。
Solr3.6.1 在Tomcat6下的環境搭建 http://www.cnblogs.com/chinway/p/6187260.html
基於Tomcat的Solr3.5集群部署 http://www.cnblogs.com/chinway/p/6187271.html
在Linux上使用Nginx為Solr集群做負載均衡 http://www.cnblogs.com/chinway/p/6187292.html
Linux下安裝使用Solr http://www.cnblogs.com/chinway/p/6187322.html
Solr實現Low Level查詢解析(QParser) http://www.cnblogs.com/chinway/p/6187332.html
Solr 4.0 部署實例教程 http://www.cnblogs.com/chinway/p/6187382.html
三、全文檢索引擎Solr系列—–全文檢索基本原理
新華字典,我們都使用過,如叫你翻開第38頁,找到“坑爹”所在的位置,此時你會怎么查呢?毫無疑問,你的眼睛會從38頁的第一個字開始從頭至尾地掃描,直到找到“坑爹”二字為止。這種搜索方法叫做順序掃描法。對於少量的數據,使用順序掃描是夠用的。但是媽媽叫你查出坑爹的“坑”字在哪一頁時,你要是從第一頁的第一個字逐個的掃描下去,那你真的是被坑了。此時你就需要用到索引。索引記錄了“坑”字在哪一頁,你只需在索引中找到“坑”字,然后找到對應的頁碼,答案就出來了。因為在索引中查找“坑”字是非常快的,因為你知道它的偏旁,因此也就可迅速定位到這個字。
那么新華字典的目錄(索引表)是怎么編寫而成的呢?首先對於新華字典這本書來說,除去目錄后,這本書就是一堆沒有結構的數據集。但是聰明的人類善於思考總結,發現每個字都會對應到一個頁碼,比如“坑”字就在第38頁,“爹”字在第90頁。於是他們就從中提取這些信息,構造成一個有結構的數據。類似數據庫中的表結構:
word page_no --------------- 坑 38 爹 90 ... ...
這樣就形成了一個完整的目錄(索引庫),查找的時候就非常方便了。對於全文檢索也是類似的原理,它可以歸結為兩個過程:1.索引創建(Indexing)2. 搜索索引(Search)。那么索引到底是如何創建的呢?索引里面存放的又是什么東西呢?搜索的的時候又是如何去查找索引的呢?帶着這一系列問題繼續往下看。

索引
Solr/Lucene采用的是一種反向索引,所謂反向索引:就是從關鍵字到文檔的映射過程,保存這種映射這種信息的索引稱為反向索引

- 左邊保存的是字符串序列
- 右邊是字符串的文檔(Document)編號鏈表,稱為倒排表(Posting List)
字段串列表和文檔編號鏈表兩者構成了一個字典。現在想搜索”lucene”,那么索引直接告訴我們,包含有”lucene”的文檔有:2,3,10,35,92,而無需在整個文檔庫中逐個查找。如果是想搜既包含”lucene”又包含”solr”的文檔,那么與之對應的兩個倒排表去交集即可獲得:3、10、35、92。
索引創建
假設有如下兩個原始文檔:
文檔一:Students should be allowed to go out with their friends, but not allowed to drink beer.
文檔二:My friend Jerry went to school to see his students but found them drunk which is not allowed.
創建過程大概分為如下步驟:

一:把原始文檔交給分詞組件(Tokenizer)
分詞組件(Tokenizer)會做以下幾件事情(這個過程稱為:Tokenize),處理得到的結果是詞匯單元(Token)
- 將文檔分成一個一個單獨的單詞
- 去除標點符號
- 去除停詞(stop word)
- 所謂停詞(Stop word)就是一種語言中沒有具體含義,因而大多數情況下不會作為搜索的關鍵詞,這樣一來創建索引時能減少索引的大小。英語中停詞(Stop word)如:”the”、”a”、”this”,中文有:”的,得”等。不同語種的分詞組件(Tokenizer),都有自己的停詞(stop word)集合。經過分詞(Tokenizer)后得到的結果稱為詞匯單元(Token)。上例子中,便得到以下詞匯單元(Token):
"Students","allowed","go","their","friends","allowed","drink","beer","My","friend","Jerry","went","school","see","his","students","found","them","drunk","allowed"
- 所謂停詞(Stop word)就是一種語言中沒有具體含義,因而大多數情況下不會作為搜索的關鍵詞,這樣一來創建索引時能減少索引的大小。英語中停詞(Stop word)如:”the”、”a”、”this”,中文有:”的,得”等。不同語種的分詞組件(Tokenizer),都有自己的停詞(stop word)集合。經過分詞(Tokenizer)后得到的結果稱為詞匯單元(Token)。上例子中,便得到以下詞匯單元(Token):
二:詞匯單元(Token)傳給語言處理組件(Linguistic Processor)
語言處理組件(linguistic processor)主要是對得到的詞元(Token)做一些語言相關的處理。對於英語,語言處理組件(Linguistic Processor)一般做以下幾點:
- 變為小寫(Lowercase)。
- 將單詞縮減為詞根形式,如”cars”到”car”等。這種操作稱為:stemming。
- 將單詞轉變為詞根形式,如”drove”到”drive”等。這種操作稱為:lemmatization。
語言處理組件(linguistic processor)處理得到的結果稱為詞(Term),例子中經過語言處理后得到的詞(Term)如下:
"student","allow","go","their","friend","allow","drink","beer","my","friend","jerry","go","school","see","his","student","find","them","drink","allow"。
經過語言處理后,搜索drive時drove也能被搜索出來。Stemming 和 lemmatization的異同:
- 相同之處:
- Stemming和lemmatization都要使詞匯成為詞根形式。
- 兩者的方式不同:
- Stemming采用的是”縮減”的方式:”cars”到”car”,”driving”到”drive”。
- Lemmatization采用的是”轉變”的方式:”drove”到”drove”,”driving”到”drive”。
- 兩者的算法不同:
- Stemming主要是采取某種固定的算法來做這種縮減,如去除”s”,去除”ing”加”e”,將”ational”變為”ate”,將”tional”變為”tion”。
- Lemmatization主要是采用事先約定的格式保存某種字典中。比如字典中有”driving”到”drive”,”drove”到”drive”,”am, is, are”到”be”的映射,做轉變時,按照字典中約定的方式轉換就可以了。
- Stemming和lemmatization不是互斥關系,是有交集的,有的詞利用這兩種方式都能達到相同的轉換。
三:得到的詞(Term)傳遞給索引組件(Indexer)
- 利用得到的詞(Term)創建一個字典
Term Document ID student 1 allow 1 go 1 their 1 friend 1 allow 1 drink 1 beer 1 my 2 friend 2 jerry 2 go 2 school 2 see 2 his 2 student 2 find 2 them 2 drink 2 allow 2
- 對字典按字母順序排序:
Term Document ID allow 1 allow 1 allow 2 beer 1 drink 1 drink 2 find 2 friend 1 friend 2 go 1 go 2 his 2 jerry 2 my 2 school 2 see 2 student 1 student 2 their 1 them 2
- 合並相同的詞(Term)成為文檔倒排(Posting List)鏈表

-
- Document Frequency:文檔頻次,表示多少文檔出現過此詞(Term)
- Frequency:詞頻,表示某個文檔中該詞(Term)出現過幾次
對詞(Term) “allow”來講,總共有兩篇文檔包含此詞(Term),詞(Term)后面的文檔鏈表總共有兩個,第一個表示包含”allow”的第一篇文檔,即1號文檔,此文檔中,”allow”出現了2次,第二個表示包含”allow”的第二個文檔,是2號文檔,此文檔中,”allow”出現了1次
至此索引創建完成,搜索”drive”時,”driving”,”drove”,”driven”也能夠被搜到。因為在索引中,”driving”,”drove”,”driven”都會經過語言處理而變成”drive”,在搜索時,如果您輸入”driving”,輸入的查詢語句同樣經過分詞組件和語言處理組件處理的步驟,變為查詢”drive”,從而可以搜索到想要的文檔。
搜索步驟
搜索”microsoft job”,用戶的目的是希望在微軟找一份工作,如果搜出來的結果是:”Microsoft does a good job at software industry…”,這就與用戶的期望偏離太遠了。如何進行合理有效的搜索,搜索出用戶最想要得結果呢?搜索主要有如下步驟:
一:對查詢內容進行詞法分析、語法分析、語言處理
- 詞法分析:區分查詢內容中單詞和關鍵字,比如:english and janpan,”and”就是關鍵字,”english”和”janpan”是普通單詞。
- 根據查詢語法的語法規則形成一棵樹

- 語言處理,和創建索引時處理方式是一樣的。比如:leaned–>lean,driven–>drive
二:搜索索引,得到符合語法樹的文檔集合
三:根據查詢語句與文檔的相關性,對結果進行排序
我們把查詢語句也看作是一個文檔,對文檔與文檔之間的相關性(relevance)進行打分(scoring),分數高比較越相關,排名就越靠前。當然還可以人工影響打分,比如百度搜索,就不一定完全按照相關性來排名的。
如何評判文檔之間的相關性?一個文檔由多個(或者一個)詞(Term)組成,比如:”solr”, “toturial”,不同的詞可能重要性不一樣,比如solr就比toturial重要,如果一個文檔出現了10次toturial,但只出現了一次solr,而另一文檔solr出現了4次,toturial出現一次,那么后者很有可能就是我們想要的搜的結果。這就引申出權重(Term weight)的概念。
權重表示該詞在文檔中的重要程度,越重要的詞當然權重越高,因此在計算文檔相關性時影響力就更大。通過詞之間的權重得到文檔相關性的過程叫做空間向量模型算法(Vector Space Model)
影響一個詞在文檔中的重要性主要有兩個方面:
- Term Frequencey(tf),Term在此文檔中出現的頻率,ft越大表示越重要
- Document Frequency(df),表示有多少文檔中出現過這個Trem,df越大表示越不重要
物以希為貴,大家都有的東西,自然就不那么貴重了,只有你專有的東西表示這個東西很珍貴,權重的公式:

空間向量模型
文檔中詞的權重看作一個向量
Document = {term1, term2, …… ,term N}
Document Vector = {weight1, weight2, …… ,weight N}
把欲要查詢的語句看作一個簡單的文檔,也用向量表示:
Query = {term1, term 2, …… , term N}
Query Vector = {weight1, weight2, …… , weight N}
把搜索出的文檔向量及查詢向量放入N維度的空間中,每個詞表示一維:

夾角越小,表示越相似,相關性越大
Solr3.6.1 在Tomcat6下的環境搭建 http://www.cnblogs.com/chinway/p/6187260.html
基於Tomcat的Solr3.5集群部署 http://www.cnblogs.com/chinway/p/6187271.html
在Linux上使用Nginx為Solr集群做負載均衡 http://www.cnblogs.com/chinway/p/6187292.html
Linux下安裝使用Solr http://www.cnblogs.com/chinway/p/6187322.html
Solr實現Low Level查詢解析(QParser) http://www.cnblogs.com/chinway/p/6187332.html
Solr 4.0 部署實例教程 http://www.cnblogs.com/chinway/p/6187382.html

