Beta笔记——搜索引擎的设计与实现(1):使用Lucene.Net建立索引与中文分词

回寝室前花几分钟的时间写一下我目前对学霸搜索引擎的构建工具:Lucene.Net盘古分词的使用.

1. 简介

  Lucene.Net是优秀的Java平台下的开源搜索引擎解决方案Lucene的.Net版本,在学霸项目中,我们使用的是2.9.2版本。

  盘古分词是开源的中文分词软件,分词速度快,支持自定义词典与停词设置,能够与Lucene.Net做到无缝整合,学霸中使用的是最新的2.3.3版本。

2. Lucene.Net HelloWorld

  在测试过程中,我尝试了Lucene的多个不同版本,让我不能理解的是,不同版本的Lucene的各个操作语法出入很大,而且不同版本的索引不能够共享。下面以2.9.2版本为例,最新3.0.3版本与之有很大出入,之所以不用最新版,是为了配合盘古分词。

  首先给出一些入门的资源:

  1. How to get started with Lucene.Net
  2. The Main Concepts
  3. Your First Application
  4. Dissecting Storage Documents and Fields
  5. Lucene - or how I stopped worrying and learned to love unstructured data
  6. How Subtext Lucene.Net index is structured

   2.1 建立索引目录

  在向Lucene.Net灌入数据之前,首先需要设置索引的存放路径,Lucene.Net支持磁盘索引与内存索引,这里以磁盘索引为例:

Directory directory = FSDirectory.GetDirectory("LuceneIndex");

  2.2 建立分析器

  分析器用来对数据进行分词,便于后续建立倒排索引。

Analyzer analyzer = new StandardAnalyzer();

  2.3 建立IndexWriter

  IndexWriter用来将Document写入索引文件,并建立好倒排索引

IndexWriter writer = new IndexWriter(directory, analyzer); 

//添加索引的方法 addDocs(writer);
writer.Optimize(); writer.Commit(); writer.Close();

  其中addDocs(writer)的方法代码为:

            List<Question> qlist = new QuestionManager().GetQuestions(1);

            foreach (Question q in qlist)

            {

                Lucene.Net.Documents.Document doc = new Lucene.Net.Documents.Document();

                doc.Add(new Field("qid", q.Id.ToString(), Field.Store.YES, Field.Index.NO));

                // doc.Add(new Field("tags",q.Tags))

                doc.Add(new Field("title", q.Title, Field.Store.YES, Field.Index.ANALYZED));

                doc.Add(new Field("content", q.Content, Field.Store.YES, Field.Index.ANALYZED));

                doc.Add(new Field("created", q.PostDateTime.ToShortDateString(), Field.Store.NO, Field.Index.NOT_ANALYZED));

                doc.Add(new Field("repiles", q.Replies.ToString(), Field.Store.NO, Field.Index.NOT_ANALYZED));

                doc.Add(new Field("views", q.Views.ToString(), Field.Store.NO, Field.Index.NOT_ANALYZED));

                writer.AddDocument(doc);

            }

  2.4 搜索

  索引建立好啦,下面开始搜索,首先初始化Searcher,使用QueryParser对QueryString进行分析处理,然后提交Searcher对象,返回的结果保存在Hits中

IndexSearcher searcher = new IndexSearcher(directory,false);

QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "title", new PanGuAnalyzer(true));

//Supply conditions

string keys = "flash C++";

keys = GetKeyWordsSplitBySpace(keys, new PanGuTokenizer());

Query query = parser.Parse(keys);



//Do the search

Hits hits = searcher.Search(query);

ScoreDoc[] result = searcher.Search(query, null, 100).scoreDocs;

for (int i = 0; i < result.Length; i++)

     Console.WriteLine(searcher.Doc(result[i].doc).Get("title"));

  最后不要忘记关闭资源

analyzer.Close();

writer.Close();

directory.Close();

3. 整合盘古分词

  在测试时,我发现使用官方编译的版本整合进Lucene.Net中,无法得到搜索结果,官方blog中对问题进行了说明(http://www.cnblogs.com/eaglet/archive/2010/05/12/1733581.html#2529278),但是,我发现使用官方编译版本依旧无法得到搜索结果,无奈只能下载源码自行编译最新的2.3.3版本。

  整合过程比较简单,将StandardAnalyzer替换为PanGuAnalyzer即可。

 PanGu.Segment.Init();             Directory directory = FSDirectory.GetDirectory("LuceneIndex");

            //Analyzer analyzer = new StandardAnalyzer();

            Analyzer analyzer =new PanGuAnalyzer();             IndexWriter writer = new IndexWriter(directory, analyzer); 



            //addDocs(writer);

            writer.Optimize();

            writer.Commit();

            writer.Close();



            IndexSearcher searcher = new IndexSearcher(directory,false);

            //QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29,"title", analyzer);

            QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "title", new PanGuAnalyzer(true));

            //Supply conditions

            string keys = "flash C++";

            keys = GetKeyWordsSplitBySpace(keys, new PanGuTokenizer());

            Query query = parser.Parse(keys);



            //Do the search

            Hits hits = searcher.Search(query);

            ScoreDoc[] result = searcher.Search(query, null, 100).scoreDocs;

            for (int i = 0; i < result.Length; i++)

                Console.WriteLine(searcher.Doc(result[i].doc).Get("title"));



            analyzer.Close();

            writer.Close();

            directory.Close();

 

 

 

你可能感兴趣的:(Lucene)