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




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

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





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

這點純粹是為了方便用戶的使用.在內部Lucene自動做了轉化,效果和將它們拼接好再存是一樣.
2. 刪除索引中的文檔
這一點Lucene所采取的方式比較怪,它使用IndexReader來對要刪除的項進行標記,然后在Reader Close的時候一起刪除.
這里簡要介紹幾個方法.




















































































當然你也可以不通過文檔序號進行刪除工作.采用下面的方法,可以從索引中刪除包含特定的內容文檔.






你還可以通過reader.UndeleteAll()這個方法取消前面所做的標記,即在read.Close()調用之前取消所有的刪除工作.
3. 更新索引中的文檔
這個功能Lucene沒有支持, 只有通過刪除后在添加來實現. 看看代碼,很好理解的.
[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搜索會失敗
}
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;
}
}
需要注意的是以上所有有關索引的操作,為了避免頻繁的打開和關閉Writer和Reader.又由于添加和刪除是不同的連接(Writer, Reader)做的.所以應該盡可能的將添加文檔的操作放在一起批量執行,然后將刪除文檔的操作也放在一起批量執行.避免添加刪除交替進行.