zoukankan      html  css  js  c++  java
  • 使用Lucene.net进行全文查找多关键字匹配 拓荒者

    Lucene是一个开源的搜索引擎,开发语言是Java,Lucene.net是它的.NET版本。可以在C#中方便的调用。

    Lucene.net目前最新版本是3.0.3,你可以从官方网站下载到最新版本:http://lucenenet.apache.org/

    使用Lucene.net进行全文查找首先要根据数据创建索引,然后再根据索引来查找关键字。本文不做任何原理性的解释,需要深入研究的请自行Google之。

    创建索引

    还是直接上代码的比较好:

                IndexWriter writer = new IndexWriter(FSDirectory.Open(new DirectoryInfo(indexDirectory)),
                        analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
    
                for (int i = 0; i < files.Count(); i++)
                {
                    FileInfo fileInfo = files[i];
                    StreamReader reader = new StreamReader(fileInfo.FullName);
    
                    OutputMessage("正在索引文件[" + fileInfo.Name + "]");
    
                    Document doc = new Document();
                    doc.Add(new Field("FileName", fileInfo.Name, Field.Store.YES, Field.Index.ANALYZED));
                    doc.Add(new Field("Author", reader.ReadLine(), Field.Store.YES, Field.Index.ANALYZED));
                    doc.Add(new Field("Content", reader.ReadToEnd(), Field.Store.NO, Field.Index.ANALYZED));
                    doc.Add(new Field("Path", fileInfo.FullName, Field.Store.YES, Field.Index.NO));
    
                    writer.AddDocument(doc);
                    writer.Optimize();
                }
    
                writer.Dispose();

    在上面的代码中,我们对文本文件进行了索引,每一个文件都保存了FileName(文件名)、Author(作者)、Content(内容)、Path(文件路径)几个字段。跟数据库中的字段很相似。

    使用中文分词

    目前中文分词有Lucene.Net.Analysis.Cn.ChineseAnalyzer 和盘古分词,我们在测试中使用前者,更方便我们做测试。

    Lucene.Net.Analysis.Cn.ChineseAnalyzer包含在源代码中,你可以把它复制到你的源代码中,也可以编译以后引用。我这里为了方便,直接复制到源代码中的。建议在实际使用的时候,编译然后添加引用。

    全文查找

    还是上代码吧,看上去更直接。

                IndexReader reader = null;
                IndexSearcher searcher = null;
                try
                {
                    reader = IndexReader.Open(FSDirectory.Open(new DirectoryInfo(indexDirectory)), true);
                    searcher = new IndexSearcher(reader);
                    //创建查询
                    PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(analyzer);
                    wrapper.AddAnalyzer("FileName", analyzer);
                    wrapper.AddAnalyzer("Author", analyzer);
                    wrapper.AddAnalyzer("Content", analyzer);
                    string[] fields = {"FileName", "Author", "Content"};
    
                    QueryParser parser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30, fields, wrapper);
                    Query query = parser.Parse(keyword);
                    TopScoreDocCollector collector = TopScoreDocCollector.Create(num, true);
    
                    searcher.Search(query, collector);
                    var hits = collector.TopDocs().ScoreDocs;
    
                    int numTotalHits = collector.TotalHits;
                    OutputMessage("查找 " + keyword + " ...共找到 " + numTotalHits + "个匹配的文档");
    
                    //以后就可以对获取到的collector数据进行操作
                    for (int i = 0; i < hits.Count(); i++)
                    {
                        var hit = hits[i];
                        Document doc = searcher.Doc(hit.Doc);
                        Field fileNameField = doc.GetField("FileName");
                        Field authorField = doc.GetField("Author");
                        Field pathField = doc.GetField("Path");
    
                        OutputMessage(fileNameField.StringValue + "[" + authorField.StringValue + "],匹配指数:" + Math.Round(hit.Score * 100, 2) + "%");
                        OutputMessage(pathField.StringValue);
                        OutputMessage(string.Empty);
                    }
                }
                finally
                {
                    if (searcher != null)
                        searcher.Dispose();
    
                    if (reader != null)
                        reader.Dispose();
                }

    上面的这段代码可以是实现多关键字的查找。需要说明的是,貌似在得到检索到的文档的地方,跟之前的版本有一些不同(我拷贝别人的代码没办法直接运行)……

    另外,此处检索的行数受到num的影响,但返回的总行数是不受影响的,如果需要得到总行数,可以在第一次检索以后得到总行数,然后将总行数赋值给num,在进行新一次的检索。

    按照惯例,附上源代码  

  • 相关阅读:
    202011051 每周例行报告
    202011261 每周例行报告
    202010153 每周例行报告
    keil代码定位
    VC2008创建MFC工程遇到的问题及解决方法
    面朝大海, 春暖花
    Oracle10G数据库教程
    郁闷来了
    MPEG4与.mp4
    vs2003 使用ffmpeg,sdl时的编译问题
  • 原文地址:https://www.cnblogs.com/youring2/p/2818311.html
Copyright © 2011-2022 走看看