Lucene.Net 系列一本文介绍了什么是Lucene,Lucene能做什么.

如何从一个文件夹下的所有txt文件中查找特定的词?

本文将围绕该个实例介绍了lucene.net的索引的建立以及如何针对索引进行搜索.最后还将给出源代码供大家学习.

源代码下载

What’s Lucene
Lucene是一个信息检索的函数库(Library),利用它你可以为你的应用加上索引和搜索的功能.

Lucene的使用者不需要深入了解有关全文检索的知识,仅仅学会使用库中的一个类,你就为你的应用实现全文检索的功能.

不过千万别以为Lucene是一个象google那样的搜索引擎,Lucene甚至不是一个应用程序,它仅仅是一个工具,一个Library.你也可以把它理解为一个将索引,搜索功能封装的很好的一套简单易用的API.利用这套API你可以做很多有关搜索的事情,而且很方便.

What Can Lucene Do

Lucene可以对任何的数据做索引和搜索. Lucene不管数据源是什么格式,只要它能被转化为文字的形式,就可以被Lucene所分析利用.也就是说不管是MS word, Html ,pdf还是其他什么形式的文件只要你可以从中抽取出文字形式的内容就可以被Lucene所用.你就可以用Lucene对它们进行索引以及搜索.

How To Use Lucene --- A Simple Example
示例介绍:

为作为输入参数的文件夹下的所有txt类型的文件做索引,做好的索引文件放入index文件夹.

然后在索引的基础上对文件进行全文搜索.

1.       建立索引
IndexWriter writer = new IndexWriter("index", new StandardAnalyzer(), true);
IndexDocs(writer, new System.IO.FileInfo(args[0]));              
writer.Optimize();
writer.Close();

IndexWriter是对索引进行写操作的一个类,利用它可以创建一个索引对象然后往其中添加文件.需要注意它并不是唯一可以修改索引的类.在索引建好后利用其他类还可以对其进行修改.

构造函数第一个参数是建立的索引所要放的文件夹的名字.第二个参数是一个分析对象,主要用于从文本中抽取那些需要建立索引的内容,把不需要参与建索引的文本内容去掉.比如去掉一些a the之类的常用词,还有决定是否大小写敏感.不同的选项通过指定不同的分析对象控制.第三个参数用于确定是否覆盖原有索引的.

第二步就是利用这个writer往索引中添加文件.具体后面再说.

第三步进行优化.

第四步关闭writer.



下面具体看看第二步:

   public static void IndexDirectory(IndexWriter writer, FileInfo file)
         {
               if (Directory.Exists(file.FullName))
               {
                   String[] files = Directory.GetFileSystemEntries(file.FullName);
                   // an IO error could occur
                   if (files != null)
                   {
                       for (int i = 0; i < files.Length; i++)
                       {
                             IndexDirectory(writer, new FileInfo(files[i]));   //这里是一个递归
                       }
                   }
               }
               else if (file.Extension == ".txt")
               {
                   IndexFile(file, writer);
               }
         }



         private static void IndexFile(FileInfo file, IndexWriter writer)
         {
               Console.Out.WriteLine("adding " + file);
               try
               {
                   Document doc = new Document();                  
                   doc.Add(Field.Keyword("filename", file.FullName));

                   doc.Add(Field.Text("contents", new StreamReader(file.FullName)));

                   writer.AddDocument(doc);
               }
              
               catch (FileNotFoundException fnfe)
               {
                  
               }
     }

主要就是两个函数一个用于处理文件夹(不是为文件夹建立索引),一个用于真正为文件建立索引.

因此主要集中看一下IndexFile这个方法.首先建立Document对象,然后为Document对象添加一些属性Field.你可以把Document对象看成是虚拟文件,将来将从此获取信息.而Field则看成是描述此虚拟文件的元数据(metadata).

其中Field包括四个类型:

Keywork
该类型的数据将不被分析,而会被索引并保存保存在索引中.

UnIndexed
该类型的数据不会被分析也不会被索引,但是会保存在索引.

UnStored
和UnIndexed刚好相反,被分析被索引,但是不被保存.

Text
和UnStrored类似.如果值的类型为string还会被保存.如果值的类型Reader就不会被保存和UnStored一样.




最后将每一个Document添加到索引当中.

需要注意的是索引不仅可以建立在文件系统上,也可以建立在内存中.

例如

IndexWriter writer = new IndexWriter("index", new StandardAnalyzer(), true);

在第一个参数不是指定文件夹的名字而是使用Directory对象,并使用它的子类RAMDirectory,就可以将索引建立在内存当中.



2.       对索引进行搜索

IndexSearcher indexSearcher= new IndexSearcher(indexDir);
Query query = QueryParser.Parse(queryString, "contents",new StandardAnalyzer());
Hits hits = indexSearcher.Search(query);

第一步利用IndexSearcher打开索引文件用于后面搜索,其中的参数是索引文件的路径.

第二步使用QueryParser将可读性较好的查询语句(比如查询的词lucene ,以及一些高级方式lucene AND .net)转化为Lucene内部使用的查询对象.

第三步执行搜索.并将结果返回到hits集合.需要注意的是Lucene并不是一次将所有的结果放入hits中而是采取一次放一部分的方式.出于空间考虑.

作者 idior