1. 抽取文本.
比如将PDF以及Word中的内容以纯文本的形式提取出来.Lucene所支持的类型主要为String,为了方便同时也支持Date 以及Reader.其实如果使用这两个类型lucene会自动进行类型转换.
2. 文本分析.
Lucene将针对所给的文本进行一些最基本的分析,并从中去除一些不必要的信息,比如一些常用字a ,an, the 等等,如果搜索的时候不在乎字母的大小写, 又可以去掉一些不必要的信息.总而言之你可以把这个过程想象成一个文本的过滤器,所有的文本内容通过分析, 将过滤掉一些内容,剩下最有用的信息.
3. 写入index.
和google等常用的索引技术一样lucene在写index的时候都是采用的倒排索引技术(inverted index.) 简而言之,就是通过某种方法(类似hash表?)将常见的”一篇文档中含有哪些词”这个问题转成”哪篇文档中有这些词”. 而各个搜索引擎的索引机制的不同主要在于如何为这张倒排表添加更准确的描述.比如google有名的PageRank因素.Lucene当然也有自己的技术,希望在以后的文章中能为大家加以介绍.
doc.Add(Field.Text("contents", new StreamReader(file.FullName)));
string synonyms[] = String {"quick", "rapid", "speedy"};
Document doc = new Document();
doc.Add(Field.Text("word", baseWord));
for (int i = 0; i < synonyms.length; i++)
doc.Add(Field.Text("word", synonyms[i]));
public class DocumentDeleteTest : BaseIndexingTestCase // BaseIndexingTestCase中的SetUp方法 //建立了索引其中加入了两个Document
{
[Test]
public void testDeleteBeforeIndexMerge()
{
IndexReader reader = IndexReader.Open(dir); //当前索引中有两个Document
Assert.AreEqual(2, reader.MaxDoc()); //文档从0开始计数,MaxDoc表示下一个文档的序号
Assert.AreEqual(2, reader.NumDocs()); //NumDocs表示当前索引中文档的个数
reader.Delete(1); //对标号为1的文档标记为待删除,逻辑删除
Assert.IsTrue(reader.IsDeleted(1)); //检测某个序号的文档是否被标记删除
Assert.IsTrue(reader.HasDeletions()); //检测索引中是否有Document被标记删除
Assert.AreEqual(2, reader.MaxDoc()); //当前下一个文档序号仍然为2
Assert.AreEqual(1, reader.NumDocs()); //当前索引中文档数变成1
reader.Close(); //此时真正从物理上删除之前被标记的文档
reader = IndexReader.Open(dir);
Assert.AreEqual(2, reader.MaxDoc());
Assert.AreEqual(1, reader.NumDocs());
reader.Close();
}
[Test]
public void DeleteAfterIndexMerge() //在索引重排之后
{
IndexReader reader = IndexReader.Open(dir);
Assert.AreEqual(2, reader.MaxDoc());
Assert.AreEqual(2, reader.NumDocs());
reader.Delete(1);
reader.Close();
IndexWriter writer = new IndexWriter(dir, GetAnalyzer(), false);
writer.Optimize(); //索引重排
writer.Close();
reader = IndexReader.Open(dir);
Assert.IsFalse(reader.IsDeleted(1));
Assert.IsFalse(reader.HasDeletions());
Assert.AreEqual(1, reader.MaxDoc()); //索引重排后,下一个文档序号变为1
Assert.AreEqual(1, reader.NumDocs());
reader.Close();
}
}
reader.Delete(new Term("city", "Amsterdam"));
reader.Close();
你还可以通过reader.UndeleteAll()这个方法取消前面所做的标记,即在read.Close()调用之前取消所有的删除工作.
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;
}
}
以上所有TestCase的源代码下载.