mvc-百步飞剑-15

说明:Lucene.net的简单使用在以前的博客中做了简单介绍http://www.cnblogs.com/YK2012/p/6676942.html .其中所涉及的引用文件放置在对应的百度网盘的文件夹下.

1.1 添加搜索控制器(SearchController)

1.2 添加视图(index)

1.3 添加dll引用(Lucene.Net+PanGu+PanGu.Lucene.Analyzer+PanGu.HighLight)和字典并设置其属性为"复制到输出目录"

1.4 添加实体类(books)

1.5 根据实体类,通过T4模板生成相应的代码

1.6 配置Config文件

1.7 控制器中的代码

using BBFJ.OA.Model;
using BBFJ.OA.WebApp.Models;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace BBFJ.OA.WebApp.Controllers
{
    public class SearchController : Controller
    {
        //
        // GET: /Search/
        IBLL.IBooksService BookInfoService { get;set;}
        public ActionResult Index()
        {
            return View();
        }
        #region 01前台页面调用方法
        public ActionResult SearchContent()
        {
            if (!String.IsNullOrEmpty(Request["btnSearch"]))
            {
                //搜索内容
               List<ViewModelContent> list= SearchBookContent();
               ViewData["list"] = list;
               return View("Index");
            }
            else
            {
                CreateContent();
            }
            return Content("ok");
        } 
        #endregion
        #region 02创建索引库
        private void CreateContent()
        {
            //01创建分词后的内容放目录
            string indexPath = @"E:\LuceneNet测试文件\索引文件";
            FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());//指定索引文件(打开索引目录) FS指的是就是FileSystem
            //判断目录是否存在(还可读取数据)
            bool isUpdate = IndexReader.IndexExists(directory);
            if (isUpdate)
            {
                //判断目录是否加锁
                if (IndexWriter.IsLocked(directory))
                {
                    IndexWriter.Unlock(directory);
                }
            }
            //向索引库中写数据                                 盘古分词                                     加锁                                                                
            IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);
            //查询数据
           List<Books> list = BookInfoService.LoadEntities(c=>true).ToList();
           foreach (var book in list)
           {
               //表示一篇文档。
               Document document = new Document();
               //书的编号
               document.Add(new Field("id", book.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
               //书的标题
               document.Add(new Field("title", book.Title, Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
               //书的内容
               document.Add(new Field("content", book.ContentDescription, Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
               writer.AddDocument(document);
           }
               

            
            writer.Close();//会自动解锁。
            directory.Close();//不要忘了Close,否则索引结果搜不到
          

        }
        
        #endregion

        #region 03搜索
        private List<ViewModelContent> SearchBookContent()
        {
            //定位到索引目录
            string indexPath = @"E:\LuceneNet测试文件\索引文件";
            //对用户输入的搜索条件进行拆分。因为很多地方都可能调用=>放置在Common中
            List<string> listkw = Common.PanGuSplitWord.PanGuSplit(Request["txtSearchContent"]);
            FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory());
            IndexReader reader = IndexReader.Open(directory, true);
            IndexSearcher searcher = new IndexSearcher(reader);
            //搜索条件
            PhraseQuery query = new PhraseQuery();
            foreach (string word in listkw)
            {
                query.Add(new Term("content", word));
            }
            
            query.SetSlop(100);//多个查询条件的词之间的最大距离.在文章中相隔太远 也就无意义.(例如 “大学生”这个查询条件和"简历"这个查询条件之间如果间隔的词太多也就没有意义了。)
            //TopScoreDocCollector是盛放查询结果的容器
            TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true);
            searcher.Search(query, null, collector);//根据query查询条件进行查询,查询结果放入collector容器
            ScoreDoc[] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs;//得到所有查询结果中的文档,GetTotalHits():表示总条数   TopDocs(300, 20);//表示得到300(从300开始),到320(结束)的文档内容.
            //可以用来实现分页功能
            List<ViewModelContent> ViewModelList = new List<ViewModelContent>();
            for (int i = 0; i < docs.Length; i++)
            {
                ViewModelContent viewModel = new ViewModelContent();
                int docId = docs[i].doc;//获得查询结果的id
                Document doc = searcher.Doc(docId);//根据id找到对应的文档详细信息
                viewModel.Id = doc.Get("id");
                viewModel.Title = doc.Get("title");
                viewModel.Content = doc.Get("content");
                ViewModelList.Add(viewModel);
            }
            return ViewModelList;
        }
        #endregion
    }
}
SearchController

  1.7.1 需要对对用户输入的搜索条件进行拆分。因为很多地方都可能调用=>放置在Common中  

using Lucene.Net.Analysis;
using Lucene.Net.Analysis.PanGu;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BBFJ.OA.Common
{
    public static class PanGuSplitWord
    {
        public static List<string> PanGuSplit(string msg) 
        {
            Analyzer analyzer = new PanGuAnalyzer();
            TokenStream tokenStream = analyzer.TokenStream("", new StringReader(msg));
            Lucene.Net.Analysis.Token token = null;
            List<string> list = new List<string>();

            while ((token = tokenStream.Next()) != null)
            {
                list.Add(token.TermText());
            }
            return list;
        }
    }
}
Common=> PanGuSplitWord

  1.7.2 List<ViewModelContent>需要在Model中添加模型  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace BBFJ.OA.WebApp.Models
{
    public class ViewModelContent
    {
        public string Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
    }
}
ViewModelContent

1.8 index中的方法

@{
    Layout = null;
}
@using BBFJ.OA.WebApp.Models
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>商品搜素</title>
</head>
<body>
    <div>
        <form method="post" action="/Search/SearchContent">
            <input type="text" name="txtSearchContent" style="width:400px"/>
            <input type="submit" value="搜索" name="btnSearch"/>
            <input type="submit" value="创建索引库" name="btnCreate"/>
        </form>
        <br />
        <ul>
           @if (ViewData["list"]!=null)
           {
                foreach (ViewModelContent viewModel in (List<ViewModelContent>)ViewData["list"])
                {
                    <li>@viewModel.Title</li>
                    <li>@viewModel.Content</li>
                }
           }
        </ul>
    </div>
</body>
</html>
View Code

 运行结果

2.0 进一步美化

2.1 高亮变红

using Lucene.Net.Analysis;
using Lucene.Net.Analysis.PanGu;
using PanGu;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BBFJ.OA.Common
{
    public static class PanGuSplitWord
    {
        public static List<string> PanGuSplit(string msg) 
        {
            Analyzer analyzer = new PanGuAnalyzer();
            TokenStream tokenStream = analyzer.TokenStream("", new StringReader(msg));
            Lucene.Net.Analysis.Token token = null;
            List<string> list = new List<string>();

            while ((token = tokenStream.Next()) != null)
            {
                list.Add(token.TermText());
            }
            return list;
        }
        // /创建HTMLFormatter,参数为高亮单词的前后缀
        public static string CreateHightLight(string keywords, string Content)
        {
            PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter =
             new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>");
            //创建Highlighter ,输入HTMLFormatter 和盘古分词对象Semgent
            PanGu.HighLight.Highlighter highlighter =
            new PanGu.HighLight.Highlighter(simpleHTMLFormatter,
            new Segment());
            //设置每个摘要段的字符数
            highlighter.FragmentSize = 150;
            //获取最匹配的摘要段
            return highlighter.GetBestFragment(keywords, Content);

        }
    }
}
common中添加高亮显示方法

控制器中修改此处,高亮显示: viewModel.Content = Common.PanGuSplitWord.CreateHightLight(Request["txtSearchContent"], doc.Get("content"));

Index中使其不对其进行编码: <dd>@MvcHtmlString.Create(viewModel.Content)</dd>

 
              

运行效果

posted @ 2017-04-08 09:08  逍遥小天狼  阅读(28)  评论(0)    收藏  举报