初探Lucene

一 Lucene简介
Lucene 是Apache软件基金会Jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。
       Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
 Lucene 可以对任何的数据做索引和搜索。Lucene不管数据源是什么格式,只要它能被转化为文字的形式,就可以被Lucene所分析和利用。也就是说不管是Word、Html、PDF还是其它什么形式的文件只要你可以从中抽取出文字形式的内容,就可以被Lucene所用,就可以用Lucene对它们进行索引和搜索。
Lucene 作为一个全文检索引擎,具有如下突出的优点:
1.           索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。
2.           在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。
3.           优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能。
4.           设计了独立于语言和文件格式的文本分析接口,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。
5.           已经默认实现了一套强大的查询引擎,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询(Fuzzy Search)、分组查询等等。
NLucene 是Lucene在.Net环境中的实现,其基本的原理和架构都是一致的,体系结构如下图:
 
1.      NLucene.Search: 搜索模块,根据查询条件,检索得到结果;
2.      NLucene.Index: 索引模块,负责索引的建立、删除等;
3.      NLucene.Analysis: 语言分析器,主要用于分词,支持各种语言主要是扩展此类;
4.      NLucene.QueryParser: 查询分析器,实现查询关键词间的运算,如与、或、非等;
5.      NLucene.Document: 索引存储的文档结构,类似与关系型数据库的表结构;
6.      NLucene.Store: 索引数据存储模块,主要包括一些底层的I/O操作;
7.      NLucene.Util: 一些公用的数据结构。
二 建立索引和搜索的代码示例
    public class NluceneTester
    {
        private const string INDEX_DIR = @"E:/Materials/OpenSource/NLUCENE/nluceneTest/IndexFile";
        public static void IndexFile()
        {
           
            try
            {
                IndexWriter writer = new IndexWriter(INDEX_DIR, new StandardAnalyzer(), true);
                System.Console.Out.WriteLine("Indexing to directory '" + INDEX_DIR + "'...");
                IndexDocs(writer);
                System.Console.Out.WriteLine("Optimizing...");
                writer.Optimize();
                writer.Close();
            }
            catch (System.IO.IOException e)
            {
                System.Console.Out.WriteLine(" caught a " + e.GetType() + "/n with message: " + e.Message);
            }
        }
 
        private static void IndexDocs(IndexWriter writer)
        {
            try
            {
                TextReader reader = File.OpenText(@"E:/Materials/OpenSource/NLUCENE/nluceneTest/config.txt");
                Document doc1 = new Document();
                doc1.Add(new Field("Features", "bearing bolt metal desk", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc1.Add(new Field("Common1", "path file index", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc1.Add(new Field("Common2", "patho fileo indexo", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc1.Add(new Field("Common3", "pathoo fileoo indexoo", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc1.Add(new Field("Name", "doc1", Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                Field contentField = new Field("Content", reader, Field.TermVector.WITH_POSITIONS_OFFSETS);
               doc1.Add(contentField);
                writer.AddDocument(doc1);
                reader.Close();
                reader = File.OpenText(@"E:/Materials/OpenSource/NLUCENE/nluceneTest/config.txt");
                Document doc2 = new Document();
                doc2.Add(new Field("Features", "bearing window door desk", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc2.Add(new Field("Common1", "debug data (1982)", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc2.Add(new Field("Common2", "debugoo data (tool))))", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc2.Add(new Field("Common3", "debugo datao toolo", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc2.Add(new Field("Name", "doc2", Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
                //doc2.Add(new Field("Content", reader, Field.TermVector.WITH_POSITIONS_OFFSETS));
                writer.AddDocument(doc2);
                reader.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
 
        }
 
        public static void Search()
        {
            string searchValue = "data (tool)";
            string filterValue = "(bearing AND bolt) OR (bearing)";
            StandardAnalyzer analyzer = new StandardAnalyzer();
            string[] commonFields = new string[] { "Common1", "Common2", "Common3", "Content" };
            // 特别注意Query searchQuery = MultiFieldQueryParser.Parse(searchValue, commonFields, occurs, 、、analyzer)
           // 与下面构造的查询逻辑的区别;
           //
            QueryParser searchQueryParser = new MultiFieldQueryParser(commonFields, analyzer);
            Query searchQuery = searchQueryParser.Parse(searchValue);
            string[] filterFields = new string[]{"Features"};
            QueryParser filterQueryParser = new MultiFieldQueryParser(filterFields, analyzer);
            Query filterQuery = filterQueryParser.Parse(filterValue);
            BooleanQuery lastQuerty = new BooleanQuery();
            lastQuerty.Add(searchQuery, BooleanClause.Occur.MUST);
            lastQuerty.Add(filterQuery, BooleanClause.Occur.MUST);
            IndexReader indexReader = IndexReader.Open(INDEX_DIR);
            Searcher searcher = new IndexSearcher(indexReader);
            // 利用搜索模块进行全文搜索.
           //
            Hits results = searcher.Search(searchQuery);
           // 调用Lucene的Hight模块对匹配的字符高亮显示.
           //
            Query minquery = searchQuery.Rewrite(indexReader);
            SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<b>", "</b>");
            for (int i = 0; i < results.Length(); ++i)
            {
                TokenStream tokenstream = null;
                Highlighter highlighter = new Highlighter(formatter, new QueryScorer(minquery));
                Fragmenter textfragmenter = new SimpleFragmenter(5);
                highlighter.SetTextFragmenter(textfragmenter);
               // 获得当前结果中“Common2”Field中所有Token的位置偏移量.
               //
                TermPositionVector tpv = (TermPositionVector)indexReader.GetTermFreqVector(results.Id(i), "Common2");
                if (null == tpv)
                    return;
                tokenstream = TokenSources.GetTokenStream(tpv);
                 // 对Field“Common2”中的匹配字段加上高亮格式.改函数内部利用之前的Query条件又搜索了一遍.
                 //
                string temp = highlighter.GetBestFragments(tokenstream, results.Doc(i).Get("Common2"), 2, "...");
                Console.WriteLine(temp);
            }
            searcher.Close();
            indexReader.Close();
        }
    }
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值