场景:搜索关键词进行内容搜索,且需要性能要求如图:
怎么做到,大概的思路就是就是把整个需要作为搜索的内容,例如文章标题、文章内容,拆解细小碎片化的内容,并建立对应的索引。当搜索的时候,就可以把搜索关键词也进行拆解细小碎片化的内容,去需要对应的索引,以此来关联搜索的内容。大致流程如下:
代码封装片段:
using Lucene.Net.Analysis;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Store;
using LuncennePro.Models;
using System.Collections.Generic;
namespace LuncennePro.LuncenceService
{
public class ManualBulidIndex
{
/// <summary>
/// 创建索引
/// </summary>
/// <param name="list">请求实体</param>
/// <param name="isAppend">是否全量更新</param>
public static void BulidIndex(List<ManualQuickSearchResponse> list, bool isAppend)
{
if (list == null || list.Count == 0)
{
list = new List<ManualQuickSearchResponse>();
}
var dirpath = ComConstant.LucenceIndexPath;
if (!System.IO.Directory.Exists(dirpath))
{
System.IO.Directory.CreateDirectory(dirpath);
}
var directory = FSDirectory.Open(dirpath);//文件夹
using (IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), isAppend, IndexWriter.MaxFieldLength.LIMITED))//索引写入器
{
foreach (var item in list)
{
Document doc = ParseCItoDoc(item);
writer.AddDocument(doc);//写进去
}
writer.Optimize();
}
}
/// <summary>
/// 将实体转换成doc
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public static Document ParseCItoDoc(ManualQuickSearchResponse item)
{
Document doc = new Document();
doc.Add(new Field(nameof(ManualQuickSearchResponse.Id), item.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field(nameof(ManualQuickSearchResponse.Title), item.Title, Field.Store.YES, Field.Index.ANALYZED) { Boost = 5 });//分词
doc.Add(new Field(nameof(ManualQuickSearchResponse.Content), item.Content, Field.Store.YES, Field.Index.ANALYZED));//分词
return doc;
}
}
}
public class ManualQuery
{
#region QueryManualModel
/// <summary>
/// 查询
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalCount"></param>
/// <param name="keywords"></param>
/// <param name="categoryIdList"></param>
/// <param name="idOrderBy"></param>
/// <returns></returns>
public List<ManualQuickSearchResponse> GetManualList(int pageIndex, int pageSize, out int totalCount, string keywords, string idOrderBy)
{
totalCount = 0;
var luceneQuery = new LuceneQuery();
if (string.IsNullOrWhiteSpace(keywords))
{
return null;
}
string queryString = string.Format(" {0} {1}", $" {AnalyzerKeyword(keywords, nameof(ManualQuickSearchResponse.Title))}", $" {AnalyzerKeyword(keywords, nameof(ManualQuickSearchResponse.Content))}");
return luceneQuery.QueryIndexPage(keywords, queryString, pageIndex, pageSize, out totalCount, idOrderBy);
}
#endregion QueryPdfModel
/// <summary>
/// 为keyword做盘古分词
/// </summary>
/// <param name="keyword">关键词</param>
/// <param name="type">字段</param>
/// <returns></returns>
private string AnalyzerKeyword(string keyword, string type)
{
StringBuilder queryStringBuilder = new StringBuilder();
LuceneAnalyze analyzer = new LuceneAnalyze();
string[] words = analyzer.AnalyzerKey(keyword);
if (words.Length == 1)
{
queryStringBuilder.AppendFormat("{0}:{1}* ", type, words[0]);
}
else
{
StringBuilder fieldQueryStringBuilder = new StringBuilder();
foreach (string word in words)
{
queryStringBuilder.AppendFormat("{0}:{1} ", type, word);
}
}
string result = queryStringBuilder.ToString().TrimEnd();
return result;
}
}
调用端代码:
public class HomeController : Controller
{
public ActionResult Index(string searchKey)
{
var list = new List<ManualQuickSearchResponse>();
if (!string.IsNullOrWhiteSpace(searchKey))
{
list = new ManualQuery().GetManualList(1, 10, out int totalCount, searchKey.Trim(), string.Empty);
}
return View(list);
}
/// <summary>
/// 初始化索引
/// </summary>
/// <returns></returns>
public bool Init()
{
var list = new List<ManualQuickSearchResponse>
{
new ManualQuickSearchResponse
{
Id =1,
Title="四川遂宁环保局32人集体受贿 一个局的领导几乎全军覆没",
Content=@"2017年12月,遂宁市纪委对遂宁市环保局,启动审查调查工作。结果,遂宁市环保局干部10人被查处,其中,县级干部6人、科级及以下干部4人。
县级干部6人:原党组成员、市环境监测站站长张凯;原党组成员、总工程师付小斌;党组成员、副局长邹凯;党组成员、副局长沈剑飞;党组成员杨永生;原局长、党组书记梁仲勋(已退休)。
科级及以下干部4人:监测站原副站长唐红军;是否还有单位的其他摄影器材在你那儿监测站原办公室主任王洁;信息中心原干部李相成;环科所原所长黄浩。共收缴违规违纪违法所得632万元。其中,收缴以上10人违纪违法所得565万元,另有全市环保系统50人主动说明问题并退交违规所得67万元。"
},
new ManualQuickSearchResponse
{
Id =2,
Title="央视新闻:“奔驰女车主维权”个案可以和解,根源还须深挖,致歉",
Content=@"维权靠“闹”不是一个法治社会应有的现象,也不是一个消费型经济体该出现的现象。从这个角度讲,西安奔驰女车主维权事件应该成为一个契机,真正推动中国消费市场向着法治化、公平化的轨道更进一步,才是我们今天关注这一事件的初衷。
西安奔驰车主维权一事又有了新的进展,针对车主所反映的金融服务费问题,国家税务总局西安高新技术产业开发区税务局前往西安利之星4S店进行了相关调查取证工作。16日,税务部门回应:奔驰车主王女士支付的金融服务费实际支付给了第三方公司,实为“垫资担保”费用。
此外,北京梅赛德斯奔驰销售服务公司发布声明,再度致歉,并表示立即暂停该授权店的销售运营,如果调查结果显示经销商存在不合法不合规的行为,将终止其授权。
16日晚,维权的奔驰车主王女士和西安利之星汽车有限公司已达成换车、补偿等和解协议(内容包括奔驰方面的道歉、换一台新车、退还金融服务费、车内装饰升级等),涉事车辆有关质量问题也已进入鉴定程序。"
},
new ManualQuickSearchResponse
{
Id =3,
Title="部长退休后摄影器材跟着退休 政府要3次才全要回",
Content=@"来源:中国纪检监察报跟着“退休”的摄影器材
“全市机构改革正在进行中,我们想借这次机会开展一次固定资产清查,我这次来,就是想邀请派驻纪检监察组对资产清查进行监督。”3月28日一上班,黑龙江省佳木斯市交通运输局党组书记、局长于波便来到市纪委监委驻市交通运输局纪检监察组组长李立新的办公室,开门见山说明了来意。
李立新果断答应了局党组的邀请。主动邀请纪检监察组进行监督,缘于去年该局出现的一起违纪案。
“组长,这两天我听交通运输局的同事在议论,再度致歉说以前陶部长在的时候,交通运输局内设的宣传部‘长枪短炮’啥都有,现在部长一退休,这些器材也都跟着‘退休’不见了。”2017年12月的一天,市纪委驻市交通运输局纪检组内部情况通报会上,纪检组干部小孙反映的一条信息引起了大家注意。
“有议论说明不是空穴来风,这个情况我会后和交通运输局党组沟通,督促他们尽快自查。”组长李立新当即表态。
市交通运输局党组得知这一信息后,指派了一名党组成员负责此事,并找到已经退休回家的交通运输局宣传部原部长陶英杰谈话,要求其对此情况作出说明。随后,陶英杰返还了一部单反相机和镜头。
事情本该到此结束,但是几天后,市纪委信访室转来一封举报信,信中直指陶英杰仍然占有单位多部摄影摄像器材……
在取得市交通运输局党组的支持后,纪检组针对陶英杰可能还存在占用公共财物的问题,与相关人员进行了谈话。
然而,随着谈话的深入,问题却越来越不清晰了。原来,市交通运输局宣传部主管领导和工作人员调整频繁,除了陶英杰外,谁也说不清宣传部到底有多少“家底”。无奈之下,纪检组决定直接向陶英杰了解情况。
“除了你已经归还的相机和镜头,是否还有单位的其他摄影器材在你那儿?”2018年1月初,纪检组与陶英杰进行第一次“正面交锋”。
“没有了,所有在我那儿的摄影摄像器材上次我都还回来了。”陶英杰直接否认。
“根据我们掌握的情况,2011年局里还曾给宣传部配备过一台索尼高清摄像机和专用长焦镜头,这些设备在哪儿?”
“那台高清摄像机已经换成掌中宝数码摄像机,交给执法部门使用了;长焦镜头换成两台具有夜视功能的摄像机交给前任局长了。”陶英杰不假思索地回答。
“那交接手续和单据呢?”
“都过去好多年了,我不记得了,而且只是一部机器,领导同意后,也就没留什么字据。”陶英杰一边搓着手一边说。"
},
new ManualQuickSearchResponse
{
Id =4,
Title="吉林市委原书记落马:投3亿客运站烂尾又投10亿新建",
Content=@"几天前我在推文里谈到过,深圳两任政法委书记落马,很可能已经对政法系统的政治生态造成了某种影响。话音刚落,就有消息称深圳福田区原区委副书记、政法委书记余智晟清明节后被带走调查,并明确指余智晟与刚被“双开”的深圳原市委副书记、政法委书记李华楠有关。余智晟弃政从商已经一年半了,现在看起来他还算个聪明人,很可能当时就嗅出了某些风向。但他的聪明又不“究竟”,有心事就找组织唠唠呗,“一走”岂能“了之”。
离深圳很远,但反腐态势又有些像的还有吉林。4月15日,吉林省政府原副秘书长、吉林市委原书记赵静波落马。媒体很快发现,这已经是吉林市4年来落马的第三个原市委书记。前两个分别是从一汽集团“掌门人”位置上落马的徐建一,以及从吉林省人大常委会副主任位置上退休后又被查的周化辰。
吉林市,是唯一一个和省同名的城市,甚至吉林省的名字都由此而来。你信不信,这种文辞上的巧合往往意味着某种现实影响力。何况这里六十多年前还曾是省会,何况这里还是仅次于长春的省内第二大城市。就是这样一个在吉林省内有着独特地位的城市,这几年来不但落马了三任市委书记,大小官员简直“更吹落,星如雨”。
比如市委常委、宣传部长朱淳,原吉林市副市长、在取得市交通运输局党组的支持后省住建厅副厅长魏连章,吉林市政协主席崔振吉,市城建委主任孙壮,市城建委原副主任刘彦光,原吉林市纪委书记、长春市委副书记杨子明。名字这么多,百家姓都快不够用了。在吉林市工作近十年先后担任市长、市委书记,赵静波与这些人或多或少都有交集。
吉林省的官员落马后,外界总是很难找到什么蛛丝马迹,吉林市也是如此。这样密不透风的地方,往往意味着往事太多。省委巡视组对于吉林市的巡视就很说明问题。2016年赵静波还在任市委书记,吉林省委第二巡视组当面向他反馈了巡视情况。"
},
};
ManualBulidIndex.BulidIndex(list, true);
return true;
}
}
@model List<LuncennePro.Models.ManualQuickSearchResponse>
<head>
<title>全文基础检索Demo</title>
<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
//初始化索引
function initIndex() {
$.get("/Home/Init", { rnd: Math.random() }, function (responseText) {
if (responseText == 'True') {
alert("初始化成功");
}
});
}
</script>
</head>
<body>
<h2>全文基础检索Demo</h2>
<div>
@using (Html.BeginForm("Index", "Home", FormMethod.Get, new { @id = "mainform" }))
{
<span>关键词:</span> <input type="text" value="" name="searchKey" />
<br />
<br />
<input type="submit" value="查询" />
<input type="button" value="初始化索引" onclick="initIndex()" />
<br />
<hr />
<br />
<table border="1" style="width:100%">
<tr>
<th width="30px">Id</th>
<th width="250px">标题</th>
<th>内容</th>
</tr>
@{
if (Model == null)
{
return;
}
foreach (var item in Model)
{
<tr>
<td>@item.Id</td>
<td>@Html.Raw(item.Title)</td>
<td>@Html.Raw(item.Content)</td>
</tr>
}
}
</table>
}
</div>
</body>
运行效果:
完整的代码Demo下载:https://pan.baidu.com/s/1KZdEOmnw5SeAy2y5L_gjEw qci4