前言

首先,关于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 = ;
count = ; 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 * , true);
search.Search(bq, null, collector);
TopDocs topDoc = collector.TopDocs(, collector.GetTotalHits()); //搜索结果总数超出指定收集器大小,则摈弃
if (topDoc.totalHits > pageSize * )
count = pageSize * ;
else
count = topDoc.totalHits; int i = (currentPage - ) * 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 = ; //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;
}

控制器

        public ActionResult Index(string id = "", string kw = "", string isLike = "", int pageIndex = )
{
string strKeyWorld = HttpDecode(id.Length == ? kw : id);
int pageSize = ;
int intCount = ;
int intPageCount = ;
bool _boolisLike = isLike == "" ? true : false;
List<StoreInfo> StoreInfoList = null;
Stopwatch watch = new Stopwatch();
watch.Start();//调用方法开始计时 if (strKeyWorld.Length > )
{
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视图

注意: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="" /><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 ? "":"";
@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")

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();

下一篇将继续折腾添加索引和删除索引,和数据库保持同步。

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

谢谢。

原文地址:http://www.cnblogs.com/lxsweat/p/4386420.html

瞎折腾之 Lucene.Net + MVC 搜索功能(上)的更多相关文章

  1. 如何使用 Lucene 做网站高亮搜索功能?

    现在基本上所有网站都支持搜索功能,现在搜索的工具有很多,比如Solr.Elasticsearch,它们都是基于 Lucene 实现的,各有各的使用场景.Lucene 比较灵活,中小型项目中使用的比较多 ...

  2. 【Lucene】Apache Lucene全文检索引擎架构之搜索功能3

    上一节主要总结了一下Lucene是如何构建索引的,这一节简单总结一下Lucene中的搜索功能.主要分为几个部分,对特定项的搜索:查询表达式QueryParser的使用:指定数字范围内搜索:指定字符串开 ...

  3. 如何在Web前端实现CAD图文字全文搜索功能之技术分享

    现状 在CAD看图过程中我们经常会需要用到查找文字的功能,在AutoCAD软件查找一个文字时,可以通过打开左下角输入命令find,输入查找的文字,然后设置查找范围,就可以搜索到需要查询的文字.但在We ...

  4. 瞎折腾之 NHibernate ORM框架的接触(MVC + Repository源码)(一)

    在这炮火连天.技术更新迅猛的年代,不接触了解.甚至会用2~3种框架都不好意思说自己有多少年工作经验.况且出去面试也会有点吹牛的底子嘛. 这次折腾了NHibernate.其实这些ORM框架封装好了都是给 ...

  5. Lucene 搜索功能

    搜索过程 图解: 主要 API: IndexSearcher:    //所有搜索都通过 IndexSearcher 进行,他们将调用该类中重载的 search() 方法 Query:         ...

  6. 【Lucene3.6.2入门系列】第03节_简述Lucene中常见的搜索功能

    package com.jadyer.lucene; import java.io.File; import java.io.IOException; import java.text.SimpleD ...

  7. Lucene5.5.4入门以及基于Lucene实现博客搜索功能

    前言 一直以来个人博客的搜索功能很蹩脚,只是自己简单用数据库的like %keyword%来实现的,所以导致经常搜不到想要找的内容,而且高亮显示.摘要截取等也不好实现,所以决定采用Lucene改写博客 ...

  8. 011.Adding Search to an ASP.NET Core MVC app --【给程序添加搜索功能】

    Adding Search to an ASP.NET Core MVC app 给程序添加搜索功能 2017-3-7 7 分钟阅读时长 作者 本文内容 1.Adding Search by genr ...

  9. asp.net mvc 简单搜索功能

    View中代码: <input type="text" class="searchText" id="searchText"/> ...

随机推荐

  1. sublime text3 插件安装

    安装Package control 先打开安装代码的命令行 按 ctrl+~或者 view  -> show console 将下面的代码粘贴到输入框里 按回车 import urllib.re ...

  2. JavaScript 性能分析新工具 OneProfile

    OneProfile 是一个网页版的小工具,可以用全新的方式展示 JavaScript 性能分析的结果,帮助开发者洞悉函数调用关系,优化应用性能. 点击打开 OneProfile 背景 Chrome ...

  3. Wildcard Matching

    Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. ...

  4. POJ 2464 Brownie Points II (树状数组,难题)

    题意:在平面直角坐标系中给你N个点,stan和ollie玩一个游戏,首先stan在竖直方向上画一条直线,该直线必须要过其中的某个点,然后ollie在水平方向上画一条直线,该直线的要求是要经过一个sta ...

  5. POJ 1989

    #include <iostream> #define MAXN 10005 using namespace std; bool mark[MAXN]; int main() { //fr ...

  6. Activity学习(五)——Bundle机制

    上一篇文章我简单介绍了Activity之间简单切换,很简单,这一篇文章我们继续聊Android中程序页面互相跳转的Activity,不过这一次我们在Activity跳转时,携带一些简单的数据,然后在新 ...

  7. 创建CancellationTokenSource对象用于取消Task

    虽然使用线程池ThreadPool让我们使用多线程变得容易,但是因为是由系统来分配的,如果想对线程做精细的控制就不太容易了,比如某个线程结束后执行一个回调方法.恰好Task可以实现这样的需求.这篇文章 ...

  8. 8天学通MongoDB——第一天 基础入门

    原文地址:http://www.cnblogs.com/huangxincheng/archive/2012/02/18/2356595.html 关于mongodb的好处,优点之类的这里就不说了,唯 ...

  9. React编写文本评论框

    一.需求分析 二.代码 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset= ...

  10. 对话框上右下角显示resize icon(可以拖动改变对话框的大小)(在WM_CREATE的时候,增加WS_THICKFRAME风格)

    CStatusBar m_StatusBar;  // 成员变量 // 全局变量 static UINT auIDStatusBar[] = { ID_SEPARATOR }; //在对话框类的WM_ ...