你的位置:首页 > ASP.net教程

[ASP.net教程]瞎折腾之 Lucene.Net + MVC 搜索功能


前言

首先,关于Lucene.Net 的文章已经很多了。我这次决定写出来只是为了练练手,虽然在别人看来没什么用,但是自己确实是手动实践了一把。我个人觉得还是有意义的。爱折腾、敢于实践、才能有所收获,才能发现问题。不要怕自己写的东西有问题,有问题才更好呢,可以让更多的人看见,提意见的当然是好,鄙视的……我也接受,给自己 动力去思考。

想让自己时刻保持着这种程序员-->代码心态、人都是带有惰性的,一旦玩起来 呵呵...

效果显示

进入主题

相信大家对于LuceneNet 并不陌生了,园子里面的文章很多。

参考文章:

http://www.cnblogs.com/birdshover/category/152283.html

http://www.cnblogs.com/psforever/archive/2011/10/06/2200019.html

 

界面是一个在线工具自己手动构的,可以随意的设计自己想要的界面。但是引用的css居然不是Bootstrap的css,这点得注意。

css样式引用地址:http://www.bootcss.com/p/layoutit/css/bootstrap-combined.min.css

            http://www.bootcss.com/p/layoutit/css/layoutit.css

在线工具地址:http://www.bootcss.com/p/layoutit/

 

数据库大概8w条记录,每次最多取出1W条查询结果。正常人也不会看完这么多的。

 核心代码

方法

    /// <summary>    /// 获得搜索列表    /// </summary>    /// <param name="keyword">关键字</param>    /// <param name="pageSize"></param>    /// <param name="currentPage">当前页码</param>    /// <param name="count"></param>    /// <param name="pageCount"></param>    /// <param name="isLike">是否开启模糊查询</param>    /// <returns></returns>    public static List<StoreInfo> GetSearchList(string keyword, int pageSize, int currentPage, out int count, out int pageCount, bool isLike = false)    {      string keywords = keyword; //获取用户输入关键字,以备设置高亮显示      string strIndexPath = INDEX_STORE_PATH;      List<StoreInfo> storeList = new List<StoreInfo>();      StoreInfo modelstore;      pageCount = 0;      count = 0;      IndexSearcher search = null;      try      {        search = new IndexSearcher(FSDirectory.Open(new System.IO.DirectoryInfo(strIndexPath)), true);      }      catch (Exception)      {        return null;      }      keyword = GetKeyWordsSplitBySpace(keyword, new PanGuTokenizer());      QueryParser titleQueryParser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "body", new PanGuAnalyzer(true));      Query titleQuery = titleQueryParser.Parse(keyword);      Query PrefixQuery_title = null;      Query PrefixQuery_body = null;      Query FuzzyQuery_Title = null;      Query FuzzyQuery_body = null;      Query WildcardQuery_title = null;      Query WildcardQuery_body = null;      if (isLike)      {        //以什么开头,输入“ja”就可以搜到包含java和javascript两项结果了        PrefixQuery_title = new PrefixQuery(new Term("title", keywords));        PrefixQuery_body = new PrefixQuery(new Term("body", keywords));        //直接模糊匹配,假设你想搜索跟‘wuzza’相似的词语,你可能得到‘fuzzy’和‘wuzzy’。        FuzzyQuery_Title = new FuzzyQuery(new Term("title", keywords));        FuzzyQuery_body = new FuzzyQuery(new Term("body", keywords));        //通配符搜索        WildcardQuery_title = new WildcardQuery(new Term("title", keywords));        WildcardQuery_body = new WildcardQuery(new Term("body", keywords));      }      //MultiFieldQueryParser      BooleanQuery bq = new BooleanQuery();      bq.Add(titleQuery, BooleanClause.Occur.SHOULD);//表示条件关系为“or”,BooleanClause.Occur.MUST表示“and”,BooleanClause.Occur.MUST_NOT表示“not”        if (isLike)      {        bq.Add(PrefixQuery_title, BooleanClause.Occur.SHOULD);        bq.Add(PrefixQuery_body, BooleanClause.Occur.SHOULD);        bq.Add(FuzzyQuery_Title, BooleanClause.Occur.SHOULD);        bq.Add(FuzzyQuery_body, BooleanClause.Occur.SHOULD);        bq.Add(WildcardQuery_title, BooleanClause.Occur.SHOULD);        bq.Add(WildcardQuery_body, BooleanClause.Occur.SHOULD);      }      //创建一个结果收集器(收集结果最大数为1000页)      TopScoreDocCollector collector = TopScoreDocCollector.create(pageSize * 1000, true);      search.Search(bq, null, collector);      TopDocs topDoc = collector.TopDocs(0, collector.GetTotalHits());      //搜索结果总数超出指定收集器大小,则摈弃      if (topDoc.totalHits > pageSize * 1000)        count = pageSize * 1000;      else        count = topDoc.totalHits;      int i = (currentPage - 1) * pageSize;      #region      Lucene.Net.Documents.Document docs;      PanGu.HighLight.Highlighter highlighter;      PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter;      while (i < count && storeList.Count < pageSize)      {        modelstore = new StoreInfo();        docs = search.Doc(topDoc.scoreDocs[i].doc);        try        {          string strTitle = docs.Get("title");          string strContent = docs.Get("body");          modelstore.Store_ID = Convert.ToInt32(docs.Get("id"));          //高亮显示设置          simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<span style=\"color:red;\">", "</span>");          highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new PanGu.Segment());          highlighter.FragmentSize = 200;          //string GetBestFragment(keywords,content)方法会按照SimpleHTMLFormatter构造的格式对content中关键字进行高亮显示          //但如果content中不包含keywords则会返回空值,故需要按照如下进行判断          modelstore.Description = highlighter.GetBestFragment(keywords, strContent);          if (string.IsNullOrEmpty(modelstore.Description))          {            modelstore.Description = strContent;          }          modelstore.Store_Name = highlighter.GetBestFragment(keywords, strTitle);          if (string.IsNullOrEmpty(modelstore.Store_Name))          {            modelstore.Store_Name = strTitle;          }        }        catch (Exception e)        {          continue;        }        finally        {          storeList.Add(modelstore);          i++;        }      }      #endregion      search.Close();      pageCount = Convert.ToInt32(Math.Ceiling((double)collector.GetTotalHits() / pageSize));      return storeList;    }

View Code

控制器

    public ActionResult Index(string id = "", string kw = "", string isLike = "0", int pageIndex = 1)    {      string strKeyWorld = HttpDecode(id.Length == 0 ? kw : id);      int pageSize = 10;      int intCount = 0;      int intPageCount = 0;      bool _boolisLike = isLike == "1" ? true : false;      List<StoreInfo> StoreInfoList = null;      Stopwatch watch = new Stopwatch();      watch.Start();//调用方法开始计时      if (strKeyWorld.Length > 0)      {        StoreInfoList = LuceneNetUtils.GetSearchList(strKeyWorld, pageSize, pageIndex, out intCount, out intPageCount, _boolisLike);      }      watch.Stop();//调用方法计时结束      double time = watch.Elapsed.TotalSeconds;//总共花费的时间      ViewBag.time = time;      ViewBag.kw = strKeyWorld;      ViewBag.count = intCount;      ViewBag.pageIndex = pageIndex;      ViewBag.pageSize = pageSize;      ViewBag.intPageCount = intPageCount;      ViewBag._boolisLike = _boolisLike;      return View(StoreInfoList);    }

View Code

View视图

注意:ShowPageBarMvc是个页码条,在页面当中用的时候一定要引用所在命名空间,或者添加webConfig

@using System.Web.Optimization;@using LX.EFOPT.Web.Main.CommonUtils;@using PagedList;@using PagedList.Mvc;@model List<LX.EFOPT.Web.Main.Models.StoreInfo>@{  Layout = "/Views/Shared/_LayoutLucene.cshtml";}<script src="~/Js/jquery.ds.js"></script><div class="container-fluid">  <div class="row-fluid">    <div class="span12">      <form class="form-search" action="/LuceneNet/index/" onsubmit="return _search.checkInput();">        <input class="input-medium search-query" id="inputKw" name="kw" value="@ViewBag.kw" type="text" />        <button id="btn_search" type="submit" class="btn">查找</button>&nbsp;        <input type="checkbox" @(ViewBag._boolisLike ? "checked=checked":"") name="isLike" id="isLike" value="1" /><label for="isLike">是否开启模糊查询</label>        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        <button id="btn_createIndex1" type="button" class="btn">创建索引-方式1</button>        <button id="btn_createIndex2" type="button" class="btn">创建索引-方式2</button>      </form>      <div id="ajaxData" style="width:80%">        @{          if (Model != null)          {             <div style="margin-top:20px;"><p>获得约 @ViewBag.count 条结果,用时 @ViewBag.time 秒</p></div>            foreach (var item in Model)            {             <div style="margin-top:20px;">              <h4>@item.Store_ID @Html.Raw(item.Store_Name)</h4>              <p>@Html.Raw(item.Description)</p>              <p><a class="btn" href="javascript:;">查看更多 »</a></p>             </div>            }                      int pageIndex = ViewBag.pageIndex;           int pageSize = ViewBag.pageSize;           int intCount = ViewBag.count;           string kw = ViewBag.kw;           string isLike = ViewBag._boolisLike ? "1":"0";          @Html.ShowPageBarMvc("/LuceneNet/Index", pageIndex, pageSize, intCount, "kw=" + kw + "&isLike=" + isLike)          }          else          {            <div style="margin-top:20px;"><h4>没有找到你想要的数据</h4><p>可以更改关键字试试</p></div>          }        }      </div>    </div>  </div></div>@Scripts.Render("/LuceneNet/js/Search.js")

View Code

Js创建索引

/// <reference path="../../Js/jquery-1.7.1.min.js" />/// <reference path="../../Js/jquery.ds.js" />function LuceneNet() {  this.$_inputKw = $("#inputKw");  this.$_btn_search = $("#btn_search");  this.$_btn_createIndex1 = $("#btn_createIndex1");  this.$_btn_createIndex2 = $("#btn_createIndex2");}LuceneNet.prototype.init = function () {  var _self = this;  _self.$_btn_createIndex1.on("click", function () {    _self.createIndex(1);  });  _self.$_btn_createIndex2.on("click", function () {    _self.createIndex(2);  });};LuceneNet.prototype.checkInput = function () {  _self = this;    if (!_self.$_inputKw.val().length) {    return false;  }}LuceneNet.prototype.createIndex = function (_type) {  _self = this;  $.ds.tips.open("loading", "请稍后..");  $.ajax({    url: "/LuceneNet/CreateIndex",    type: "get",    dataType: "json",    data: { type: _type },    contentType: "application/x-www-form-urlencoded; charset=utf-8",    success: function (data) {      $.ds.tips.close();    }  });}LuceneNet.prototype.Search = function () {  _self = this;  $.ajax({    url: "/",    type: "get",    dataType: "json",    contentType: "application/x-www-form-urlencoded; charset=utf-8",    data: { kw: decodeURI(_self.$_inputKw.val()) },    success: function (data) {    }  });};var _search = new LuceneNet();_search.init();

View Code

 

源代码只是我在公司测试的一个项目,比较杂,没有办法全部提供下载。但是我会把代码上传到git或者是网盘

谢谢。