Lucene建立Index的過程:
1. 抽取文本.
比如將PDF以及Word中的內(nèi)容以純文本的形式提取出來.Lucene所支持的類型主要為String,為了方便同時(shí)也支持Date 以及Reader.其實(shí)如果使用這兩個(gè)類型lucene會(huì)自動(dòng)進(jìn)行類型轉(zhuǎn)換.
2. 文本分析.
Lucene將針對(duì)所給的文本進(jìn)行一些最基本的分析,并從中去除一些不必要的信息,比如一些常用字a ,an, the 等等,如果搜索的時(shí)候不在乎字母的大小寫, 又可以去掉一些不必要的信息.總而言之你可以把這個(gè)過程想象成一個(gè)文本的過濾器,所有的文本內(nèi)容通過分析, 將過濾掉一些內(nèi)容,剩下最有用的信息.
3. 寫入index.
和google等常用的索引技術(shù)一樣lucene在寫index的時(shí)候都是采用的倒排索引技術(shù)(inverted index.) 簡(jiǎn)而言之,就是通過某種方法(類似hash表?)將常見的”一篇文檔中含有哪些詞”這個(gè)問題轉(zhuǎn)成”哪篇文檔中有這些詞”. 而各個(gè)搜索引擎的索引機(jī)制的不同主要在于如何為這張倒排表添加更準(zhǔn)確的描述.比如google有名的PageRank因素.Lucene當(dāng)然也有自己的技術(shù),希望在以后的文章中能為大家加以介紹.
在上一篇文章中,使用了最基本的建立索引的方法.在這里將對(duì)某些問題加以詳細(xì)的討論.
1. 添加Document至索引
上次添加的每份文檔的信息是一樣的,都是文檔的filename和contents.




在Lucene中對(duì)每個(gè)文檔的描述是可以不同的,比如,兩份文檔都是描述一個(gè)人,其中一個(gè)添加的是name, age 另一個(gè)添加的是id, sex ,這種不規(guī)則的文檔描述在Lucene中是允許的.
還有一點(diǎn)Lucene支持對(duì)Field進(jìn)行Append , 如下:

string synonyms[] = String {"quick", "rapid", "speedy"};





for (int i = 0; i < synonyms.length; i++)
doc.Add(Field.Text("word", synonyms[i]));

這點(diǎn)純粹是為了方便用戶的使用.在內(nèi)部Lucene自動(dòng)做了轉(zhuǎn)化,效果和將它們拼接好再存是一樣.
2. 刪除索引中的文檔
這一點(diǎn)Lucene所采取的方式比較怪,它使用IndexReader來對(duì)要?jiǎng)h除的項(xiàng)進(jìn)行標(biāo)記,然后在Reader Close的時(shí)候一起刪除.
這里簡(jiǎn)要介紹幾個(gè)方法.




















































































當(dāng)然你也可以不通過文檔序號(hào)進(jìn)行刪除工作.采用下面的方法,可以從索引中刪除包含特定的內(nèi)容文檔.






你還可以通過reader.UndeleteAll()這個(gè)方法取消前面所做的標(biāo)記,即在read.Close()調(diào)用之前取消所有的刪除工作.
3. 更新索引中的文檔
這個(gè)功能Lucene沒有支持, 只有通過刪除后在添加來實(shí)現(xiàn). 看看代碼,很好理解的.
[TestFixture]
public class DocumentUpdateTest : BaseIndexingTestCase
{
[Test]
public void Update()
{
Assert.AreEqual(1, GetHitCount("city", "Amsterdam"));
IndexReader reader = IndexReader.Open(dir);
reader.Delete(new Term("city", "Amsterdam"));
reader.Close();
Assert.AreEqual(0, GetHitCount("city", "Amsterdam"));
IndexWriter writer = new IndexWriter(dir, GetAnalyzer(),false);
Document doc = new Document();
doc.Add(Field.Keyword("id", "1"));
doc.Add(Field.UnIndexed("country", "Netherlands"));
doc.Add(Field.UnStored("contents","Amsterdam has lots of bridges"));
doc.Add(Field.Text("city", "Haag"));
writer.AddDocument(doc);
writer.Optimize();
writer.Close();
Assert.AreEqual(1, GetHitCount("city", "Haag"));
}
protected override Analyzer GetAnalyzer()
{
return new WhitespaceAnalyzer(); //注意此處如果用SimpleAnalyzer搜索會(huì)失敗
}
private int GetHitCount(String fieldName, String searchString)
{
IndexSearcher searcher = new IndexSearcher(dir);
Term t = new Term(fieldName, searchString);
Query query = new TermQuery(t);
Hits hits = searcher.Search(query);
int hitCount = hits.Length();
searcher.Close();
return hitCount;
}
}
需要注意的是以上所有有關(guān)索引的操作,為了避免頻繁的打開和關(guān)閉Writer和Reader.又由于添加和刪除是不同的連接(Writer, Reader)做的.所以應(yīng)該盡可能的將添加文檔的操作放在一起批量執(zhí)行,然后將刪除文檔的操作也放在一起批量執(zhí)行.避免添加刪除交替進(jìn)行.