全文检索-Lucene.net

Lucene.net是Lucene的.net移植版本,在较早之前是比较受欢迎的一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。

例子的组件版本

Lucene.Net:3.0.3.0

盘古分词:2.4.0.0

分词例子

  • 分词是核心算法,将完整的句子分词成若干个词或字;同时它只能处理文本信息,非文本信息只能转换成为文本信息,无法转换的只能放弃。
  • 所有供全文搜索的要先写入索引库,索引库可以看成存放数据的数据库
  • 搜索对象建立的时候(比如文章),写入数据库的同时,也要写入索引,也就是各存一份。

Lucene.net有内置的分词算法,所有分词算法都继承Analyzer类;但对中文是按照单个字进行分词的,显然满足不了日常需求,所以常用到其他分词算法如盘古分词。

盘古分词下载后有以下dll内容

PanGu.dll :核心组件

PanGu.Lucene.Analyzer.dll :盘古分词针对Lucene.net 的接口组件,貌似词库写死在了dll文件里,没有配置词库的话,会读取dll里面的,否则直接读取配置的词库。

PanGu.HighLight.dll:高亮组件

PanGu.xml:xml文件配置,其中DictionaryPath 指明字典词库所在目录,可以为相对路径也可以为绝对路径

所需词库:

简单分词只引入PanGu.Lucene.Analyzer.dll 即可,例子如下:

        [HttpPost]
        public ActionResult Cut_2(string str)
        {
            //盘古分词
            StringBuilder sb = new StringBuilder();

            Analyzer analyzer = new PanGuAnalyzer();

            TokenStream tokenStream = analyzer.TokenStream("", new StringReader(str));

            ITermAttribute item = tokenStream.GetAttribute<ITermAttribute>();

            while (tokenStream.IncrementToken())

            {
                sb.Append(item.Term + "|");

            }
            tokenStream.CloneAttributes();
            analyzer.Close();
            return Content(sb.ToString());
        }

效果如下:

完整例子

项目前期准备:

  • 引入所需的三个dll
  • 放入PanGu.xml默认配置文件,与PanGu.dll不要在同一目录
  • 建立LuceneIndex用来存放索引数据
  • 建立Dict文件存放词典:Dict文件目录为默认词典文件目录,如不在Dict文件下,要在PanGu.xml中的DictionaryPath 指明字典词库所在目录
  1. 在进程启动时,需要对盘古分词进行初始化,初始化的调用代码如下(字典文件如果在Dict文件夹下,同时为默认配置,可以不用指定xml文件):
PanGu.Segment.Init(@"D:\seo_lucene.net_demo\bin\PanGu\PanGu.xml");
//或
PanGu.Segment.Init();

  2.创建索引

      //索引地址
      string indexPath = @"D:\学习代码\Seo-Lucene.Net\seo_lucene.net_demo\bin\LuceneIndex";

       /// <summary>
        /// 索引目录
        /// </summary>
        public Lucene.Net.Store.Directory directory
        {
            get
            {
                //创建索引目录
                if (!System.IO.Directory.Exists(indexPath))
                {
                    System.IO.Directory.CreateDirectory(indexPath);
                }
                FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
                return directory;
            }

        }
        /// <summary>
        /// 创建索引
        /// </summary>
        private void CreateIndex()
        {
            bool isExists = IndexReader.IndexExists(directory);//判断索引库是否存在
            if (isExists)
            {
                //如果因异常情况索引目录被锁定,先解锁
                //Lucene.Net每次操作索引库之前会自动加锁,在close的时候会自动解锁
                //不能多线程执行,只能处理意外被永远锁定的情况
                if (IndexWriter.IsLocked(directory))
                {
                    IndexWriter.Unlock(directory);//解锁
                }
            }

            //IndexWriter第三个参数:true指重新创建索引,false指从当前索引追加,第一次新建索引库true,之后直接追加就可以了
            IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isExists, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);

            //Field.Store.YES:存储原文并且索引
            //Field.Index. ANALYZED:分词存储
            //Field.Index.NOT_ANALYZED:不分词存储
            //一条Document相当于一条记录
            //所有自定义的字段都是string
            try
            {
                //以下语句可通过id判断是否存在重复索引,存在则删除,如果不存在则删除0条
                //writer.DeleteDocuments(new Term("id", "1"));//防止存在的数据
                //writer.DeleteDocuments(new Term("id", "2"));//防止存在的数据
                //writer.DeleteDocuments(new Term("id", "3"));//防止存在的数据

                //或是删除所有索引
                writer.DeleteAll();
                writer.Commit();
                //是否删除成功
                var IsSuccess = writer.HasDeletions();

                Document doc = new Document();
                doc.Add(new Field("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("title", "三国演义", Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc.Add(new Field("Content", "刘备、云长、翼德点精兵三千,往北海郡进发。", Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
                writer.AddDocument(doc);

                doc = new Document();
                doc.Add(new Field("id", "2", Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("title", "西游记", Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc.Add(new Field("Content", "话表齐天大圣到底是个妖猴,唐三藏。", Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
                writer.AddDocument(doc);

                doc = new Document();
                doc.Add(new Field("id", "3", Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("title", "水浒传", Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
                doc.Add(new Field("Content", "梁山泊义士尊晁盖 郓城县月夜走刘唐。", Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
                writer.AddDocument(doc);

            }
            catch (FileNotFoundException fnfe)
            {
                throw fnfe;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                writer.Optimize();
                writer.Dispose();
                directory.Dispose();
            }

        }

   3.搜索

        /// <summary>
        /// 搜索
        /// </summary>
        /// <param name="txtSearch">搜索字符串</param>
        /// <param name="id">当前页</param>
        /// <returns></returns>
        [HttpGet]
        public ActionResult Search(string txtSearch,int id=1)
        {
            int pageNum = 1;
            int currentPageNo = id;
            IndexSearcher search = new IndexSearcher(directory, true);
            BooleanQuery bQuery = new BooleanQuery();

            //总的结果条数
            List<Article> list = new List<Article>();
            int recCount = 0;
            //处理搜索关键词
            txtSearch = LuceneHelper.GetKeyWordsSplitBySpace(txtSearch);

            //多个字段查询 标题和内容title, content
            MultiFieldQueryParser parser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30,new string[] { "title", "Content" }, new PanGuAnalyzer());
            Query query =parser.Parse(txtSearch);

            //Occur.Should 表示 Or 或查询, Occur.MUST 表示 and 与查询
            bQuery.Add(query, Occur.MUST);

            if (bQuery != null && bQuery.GetClauses().Length > 0)
            {
                //盛放查询结果的容器
                TopScoreDocCollector collector = TopScoreDocCollector.Create(1000, true);
                //使用query这个查询条件进行搜索,搜索结果放入collector
                search.Search(bQuery, null, collector);
                recCount = collector.TotalHits;
                //从查询结果中取出第m条到第n条的数据
                ScoreDoc[] docs = collector.TopDocs((currentPageNo - 1) * pageNum, pageNum).ScoreDocs;
                //遍历查询结果
                for (int i = 0; i < docs.Length; i++)
                {
                    //只有 Field.Store.YES的字段才能用Get查出来
                    Document doc = search.Doc(docs[i].Doc);
                    list.Add(new Article() {
                        Id = doc.Get("id"),
                        Title = LuceneHelper.CreateHightLight(txtSearch, doc.Get("title")),//高亮显示
                        Content = LuceneHelper.CreateHightLight(txtSearch, doc.Get("Content"))//高亮显示
                    });
                }
            }
            //分页
            PagedList<Article> plist = new PagedList<Article>(list, currentPageNo, pageNum, recCount);
            plist.TotalItemCount = recCount;
            plist.CurrentPageIndex = currentPageNo;
            return View("Index", plist);
        }

效果如下:

原文地址:https://www.cnblogs.com/qiuguochao/p/9017154.html

时间: 2024-10-04 13:32:40

全文检索-Lucene.net的相关文章

[全文检索]Lucene基础入门.

本打算直接来学习Solr, 现在先把Lucene的只是捋一遍. 本文内容: 1. 搜索引擎的发展史 2. Lucene入门 3. Lucene的API详解 4. 索引调优 5. Lucene搜索结果排名规则 1 搜索引擎的发展史 1.1 搜索引擎的发展史 萌芽:Archie.Gopher 起步:Robot(网络机器人)和spider(网络爬虫) 1. Robot:网络机器人,自动在网络中运行,完成特定任务的程序,如刷票器.抢票软件等. 2. spider:网络爬虫,是一中特殊的机器人,抓取(下载

全文检索Lucene

------------恢复内容开始------------ 一,什么是全文检索 概念:先创建索引然后查询索引的过程就做全文索引.索引一次创建可以多次使用,表现为每次查询速度都很快. 二,数据的分类 结构化数据:格式固定,长度固定,数据类型固定   比如数据库的数据 非结构化数据:格式不固定,长度不固定,数据类型不固定word文档,pdf文档,邮件,html,txt 三,数据的查询 结构化数据的查询:SQL语句,查询简单,速度快 非结构化数据的查询: 从文本文件中查找出包含spring单词的文件

BOS物流管理系统-第一天

BOS物流管理系统-第一天-系统分析.环境搭建.前端框架 BoBo老师 整体项目内容目标: 对项目概述的一些理解 亮点技术的学习 注意学习方式:优先完成当天代码. 其他内容. 最终: 学到新的技术,会应用新的技术:对项目有个整体感觉: 课程安排:12天左右 主要内容: 项目整体概述和一般流程(项目概念.一般项目流程等) BOS项目的概述(项目背景.需求.技术架构.学习目标) 开发环境搭建 项目导入和运行(传统项目结构)(Struts2的通配符映射) 项目导入和运行(Maven项目结构)(STS开

我心中的核心组件(可插拔的AOP)~大话开篇及目录

我心中的核心组件(可插拔的AOP)~大话开篇及目录 http://www.cnblogs.com/lori/p/3247905.html 回到占占推荐博客索引 核心组件 我心中的核心组件,核心组件就是我认为在项目中比较常用的功能,如日志,异常处理,消息,邮件,队列服务,调度,缓存,持久化,分布式文件存储,NoSQL存储,IoC容器,方法拦截等等. 对于以上内容可以说即是一个大餐,又是一个挑战,就让我带着大家去迎接这份挑战吧,呵呵! 可插拔的AOP AOP即面向切面的编程,是指将一个公用的与领域无

2015年33期Java/Spring/Struts2/web/基础/就业班视频

一.基础班课程(掌握Java核心课程) 日期        星期        课程(空内容表示放假)        上课老师2014/12/8        星期一        [开学典礼].Java开发前奏        钟太潋2014/12/9        星期二        Java语言基础        钟太潋2014/12/10        星期三                2014/12/11        星期四        Java语言基础        钟太潋2

.NET常用第三方库(包)总结

序列化与反序列化 JSON.NET应该是.NET平台上使用最为广泛的序列化/反序列化包了,ASP.NET和ASP.NET Core中默认序列化/反序列化包 Jil官网上说性能优于JSON.NET 文本日志记录 NLog Log4Net 以上二位都是从JAVA阵营移植过来的,对于分布式系统使用文本日志追踪问题也是比较恶心的一件事儿 对象映射 AutoMapper这儿有一篇比较好的教程文章 ValueInject这个我接触的第一个对象映射库,还是比较简单的,源码读起来难度也不大 数据库 Dapper

Lucene01

数据分类 结构化数据和非结构化数据 结构化数据搜索 sql 非结构化数据查询方法 顺序扫描法 全文检索 lucene实现全文检索的流程 创建索引 对文档索引的过程,将用户要搜索的文档内容进行索引,索引存在索引库中, 获取原始文档 创建文档对象,文档中包括一个一个的域(Field),域中存储内容,可以将磁盘上的一个文件当成一个document,                      Document中包括一些Field(file_name文件名称.file_path文件路径.file_size

ElasticSearch(分布式全文搜索引擎)

1.Lucene的优化, 实现了高可用的分布式集群的搜索方案 2.首先,ES的索引库管理支持依然是基于Apache Lucene(TM)的开源搜索引擎.ES也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单. 3.ES的特点 a)  分布式的实时文件存储,每个字段都被索引并可被搜索 分布式的实时分析搜索引擎 可以扩展到上百台服务器,处理PB级结构化或非结构化数据 高度集成化的

全文检索技术---Lucene

1       Lucene介绍 1.1   什么是Lucene Lucene是apache下的一个开源的全文检索引擎工具包.它为软件开发人员提供一个简单易用的工具包(类库),以方便的在目标系统中实现全文检索的功能. 1.2   全文检索的应用场景 1.2.1  搜索引擎 ©注意: Lucene和搜索引擎是不同的,Lucene是一套用java或其它语言写的全文检索的工具包.它为应用程序提供了很多个api接口去调用,可以简单理解为是一套实现全文检索的类库.搜索引擎是一个全文检索系统,它是一个单独运