Lucene.Net 使用教程

    最近公司开发一个知识库系统,毫无疑问需要用到站内搜索的功能。最终选用Lucene.Net,现将项目中的一些收获和核心代码整理如下:

1. Lucene.Net是什么以及工作原理?

    Lucene.Net只是一个全文检索开发包,不是一个成型的搜索引擎,它的功能就是:把数据扔给Lucene.Net ,查询数据的时候从Lucene.Net 查询数据,可以看做是提供了全文检索功能的一个数据库。Lucene.Net不管文本数据怎么来的。用户可以基于Lucene.Net开发满足自己需求的搜索引擎。 Lucene.Net只能对文本信息进行检索。如果不是文本信息,要转换为文本信息,比如要检索Excel文件,就要用NPOI把Excel读取成字符串,然后把字符串扔给Lucene.Net。Lucene.Net会把扔给它的文本切词保存,加快检索速度。

 

 

 

 

2. 分词

     分词是核心的算法,搜索引擎内部保存的就是一个个的“词(Word)”。英文分词很简单,按照空格分隔就可以。中文则麻烦,把“北京,Hi欢迎你们大家” 拆成“北京 Hi 欢迎 你们 大家”。“the”,“,”,“和”,“啊”,“的”等对于搜索来说无意义的词一般都属于不参与分词的无意义单词(noise word)。

Lucene.Net中不同的分词算法就是不同的类。所有分词算法类都从Analyzer类继承,不同的分词算法有不同的优缺点。

(*)内置的StandardAnalyzer是将英文按照空格、标点符号等进行分词,将中文按照单个字进行分词,一个汉字算一个词即ChineseAnalyzer
(*)二元分词算法,每两个汉字算一个单词,“欢迎你们大家”会分词为“欢迎 迎你 你们 们大 大家”,网上找到的一个二元分词算法CJKAnalyzer。
(*)基于词库的分词算法,基于一个词库进行分词,可以提高分词的成功率。有庖丁解牛、盘古分词等。效率低

3. 盘古分词算法使用

    1.打开 PanGu4Lucene\ WebDemo \Bin ,将 Dictionaries 添加到项目根路径(改名为 Dict )
    2.添加对 PanGu.dll 、 PanGu.Lucene.Analyzer.dll 的引用。
    词库的编辑,使用 DictManage.exe ,对单词编辑的时候要先查找。工作的项目中要将行业单词添加到词库中,比如餐饮搜索、租房搜索、视频搜索等。
            Analyzer analyzer = new PanGuAnalyzer();
            TokenStream tokenStream = analyzer.TokenStream("", new StringReader(TextBox1.Text));
            Lucene.Net.Analysis.Token token = null;
            while ((token = tokenStream.Next()) != null)
            {
                Response.Write(token.TermText()+"<br/>");
            }

一下是上述代码运行的结果,分词的准确率还是很高的:

4 Lucene.Net应用实例  源代码

  1. 创建索引

View Code
 string indexPath = "c:/index";
            FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
            bool isUpdate = IndexReader.IndexExists(directory);
            if (isUpdate)
            {
                //如果索引目录被锁定(比如索引过程中程序异常退出),则首先解锁
                if (IndexWriter.IsLocked(directory))
                {
                    IndexWriter.Unlock(directory);
                }
            }
            var writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, IndexWriter.MaxFieldLength.UNLIMITED);
            var wc = new WebClient();
            wc.Encoding = Encoding.UTF8; //否则下载的是乱码

            int maxId = GetMaxId();
            for (int i = 1; i <= maxId; i++)
            {
                string url = "http://localhost:8081/showtopic-" + i + ".aspx";
                string html = wc.DownloadString(url);

                var doc = new HTMLDocumentClass();
                doc.designMode = "on"; //不让解析引擎去尝试运行javascript
                doc.IHTMLDocument2_write(html);
                doc.close();

                string title = doc.title;
                string body = doc.body.innerText; //去掉标签

                //为避免重复索引,所以先删除number=i的记录,再重新添加
                writer.DeleteDocuments(new Term("number", i.ToString()));

                var document = new Document();
                //只有对需要全文检索的字段才ANALYZED
                document.Add(new Field("number", i.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                document.Add(new Field("title", title, Field.Store.YES, Field.Index.NOT_ANALYZED));
                document.Add(new Field("body", body, Field.Store.YES, Field.Index.ANALYZED,
                                       Field.TermVector.WITH_POSITIONS_OFFSETS));
                writer.AddDocument(document);
            }
            writer.Close();
            directory.Close(); //不要忘了Close,否则索引结果搜不到;

 2.搜索

View Code
   string indexPath = "c:/index";
            string kw = TextBox1.Text;
            FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory());
            IndexReader reader = IndexReader.Open(directory, true);
            var searcher = new IndexSearcher(reader);
            var query = new PhraseQuery();

            //todo:把用户输入的关键词进行拆词

            foreach (string word in CommonHelper.SplitWord(TextBox1.Text)) //先用空格,让用户去分词,空格分隔的就是词“计算机 专业”
            {
                query.Add(new Term("body", word));
            }
            //query.Add(new Term("body","计算机"));
            //query.Add(new Term("body", "专业"));

            query.SetSlop(100);
            TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true);
            searcher.Search(query, null, collector);
            ScoreDoc[] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs;
            var listResult = new List<SearchResult>();
            for (int i = 0; i < docs.Length; i++)
            {
                int docId = docs[i].doc; //取到文档的编号(主键,这个是Lucene .net分配的)
                //检索结果中只有文档的id,如果要取Document,则需要Doc再去取
                //降低内容占用
                Document doc = searcher.Doc(docId); //根据id找Document
                string number = doc.Get("number");
                string title = doc.Get("title");
                string body = doc.Get("body");

                var result = new SearchResult();
                result.Number = number;
                result.Title = title;


                result.BodyPreview = Preview(body, TextBox1.Text);

                listResult.Add(result);
            }
            repeaterResult.DataSource = listResult;
            repeaterResult.DataBind();

3.关键字高亮

View Code
            //创建HTMLFormatter,参数为高亮单词的前后缀 
            var simpleHTMLFormatter =
                new SimpleHTMLFormatter("<font color=\"red\">", "</font>");
            //创建 Highlighter ,输入HTMLFormatter 和 盘古分词对象Semgent 
            var highlighter =
                new Highlighter(simpleHTMLFormatter,
                                new Segment());
            //设置每个摘要段的字符数 
            highlighter.FragmentSize = 100;
            //获取最匹配的摘要段 
            String bodyPreview = highlighter.GetBestFragment(keyword, body);
            return bodyPreview;

 "http://news.oceansoft.com.cn/showtopic-" + i + ".aspx";

string html = wc.DownloadString(url);

这是我从公司的内部论坛上下载页面内容,然后给这些内容建立索引。拿到代码之后需要实际情况修改

建立索引之后查询,效果如下 :

转载于:https://www.cnblogs.com/rdzzg/archive/2013/03/06/2946149.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值