转自:http://blog.csdn.net/pukuimin1226/article/details/17558247

添加:2013-12-25

更新:2013-12-26 新增分页功能。

更新:2013-12-27 新增按分类查询功能,调整索引行新增记录的图片字段。

最新盘古分词dll和词典管理工具下载:http://pangusegment.codeplex.com/

词典下载:http://pangusegment.codeplex.com/releases/view/47411

Lucene.net下载:http://lucenenet.apache.org/download.cgi

//封装类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using Lucene.Net.Analysis;
  6. using Lucene.Net.Index;
  7. using Lucene.Net.Documents;
  8. using System.Reflection;
  9. using Lucene.Net.QueryParsers;
  10. using Lucene.Net.Search;
  11. namespace SearchTest
  12. {
  13. /// <summary>
  14. /// 盘古分词在lucene.net中的使用帮助类
  15. /// 调用PanGuLuceneHelper.instance
  16. /// </summary>
  17. public class PanGuLuceneHelper
  18. {
  19. private PanGuLuceneHelper() { }
  20. #region 单一实例
  21. private static PanGuLuceneHelper _instance = null;
  22. /// <summary>
  23. /// 单一实例
  24. /// </summary>
  25. public static PanGuLuceneHelper instance
  26. {
  27. get
  28. {
  29. if (_instance == null) _instance = new PanGuLuceneHelper();
  30. return _instance;
  31. }
  32. }
  33. #endregion
  34. #region 分词测试
  35. /// <summary>
  36. /// 分词测试
  37. /// </summary>
  38. /// <param name="keyword"></param>
  39. /// <returns></returns>
  40. public string Token(string keyword)
  41. {
  42. string ret = "";
  43. System.IO.StringReader reader = new System.IO.StringReader(keyword);
  44. Lucene.Net.Analysis.TokenStream ts = analyzer.TokenStream(keyword, reader);
  45. bool hasNext = ts.IncrementToken();
  46. Lucene.Net.Analysis.Tokenattributes.ITermAttribute ita;
  47. while (hasNext)
  48. {
  49. ita = ts.GetAttribute<Lucene.Net.Analysis.Tokenattributes.ITermAttribute>();
  50. ret += ita.Term + "|";
  51. hasNext = ts.IncrementToken();
  52. }
  53. ts.CloneAttributes();
  54. reader.Close();
  55. analyzer.Close();
  56. return ret;
  57. }
  58. #endregion
  59. #region 创建索引
  60. /// <summary>
  61. /// 创建索引
  62. /// </summary>
  63. /// <param name="datalist"></param>
  64. /// <returns></returns>
  65. public bool CreateIndex(List<MySearchUnit> datalist)
  66. {
  67. IndexWriter writer = null;
  68. try
  69. {
  70. writer = new IndexWriter(directory_luce, analyzer, false, IndexWriter.MaxFieldLength.LIMITED);//false表示追加(true表示删除之前的重新写入)
  71. }
  72. catch
  73. {
  74. writer = new IndexWriter(directory_luce, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);//false表示追加(true表示删除之前的重新写入)
  75. }
  76. foreach (MySearchUnit data in datalist)
  77. {
  78. CreateIndex(writer, data);
  79. }
  80. writer.Optimize();
  81. writer.Dispose();
  82. return true;
  83. }
  84. public bool CreateIndex(IndexWriter writer, MySearchUnit data)
  85. {
  86. try
  87. {
  88. if (data == null) return false;
  89. Document doc = new Document();
  90. Type type = data.GetType();//assembly.GetType("Reflect_test.PurchaseOrderHeadManageModel", true, true); //命名空间名称 + 类名
  91. //创建类的实例
  92. //object obj = Activator.CreateInstance(type, true);
  93. //获取公共属性
  94. PropertyInfo[] Propertys = type.GetProperties();
  95. for (int i = 0; i < Propertys.Length; i++)
  96. {
  97. //Propertys[i].SetValue(Propertys[i], i, null); //设置值
  98. PropertyInfo pi = Propertys[i];
  99. string name=pi.Name;
  100. object objval = pi.GetValue(data, null);
  101. string value = objval == null ? "" : objval.ToString(); //值
  102. if (name == "id" || name=="flag" )//id在写入索引时必是不分词,否则是模糊搜索和删除,会出现混乱
  103. {
  104. doc.Add(new Field(name, value, Field.Store.YES, Field.Index.NOT_ANALYZED));//id不分词
  105. }
  106. else
  107. {
  108. doc.Add(new Field(name, value, Field.Store.YES, Field.Index.ANALYZED));
  109. }
  110. }
  111. writer.AddDocument(doc);
  112. }
  113. catch (System.IO.FileNotFoundException fnfe)
  114. {
  115. throw fnfe;
  116. }
  117. return true;
  118. }
  119. #endregion
  120. #region 在title和content字段中查询数据
  121. /// <summary>
  122. /// 在title和content字段中查询数据
  123. /// </summary>
  124. /// <param name="keyword"></param>
  125. /// <returns></returns>
  126. public List<MySearchUnit> Search(string keyword)
  127. {
  128. string[] fileds = { "title", "content" };//查询字段
  129. //Stopwatch st = new Stopwatch();
  130. //st.Start();
  131. QueryParser parser = null;// new QueryParser(Lucene.Net.Util.Version.LUCENE_30, field, analyzer);//一个字段查询
  132. parser = new MultiFieldQueryParser(version, fileds, analyzer);//多个字段查询
  133. Query query = parser.Parse(keyword);
  134. int n = 1000;
  135. IndexSearcher searcher = new IndexSearcher(directory_luce, true);//true-表示只读
  136. TopDocs docs = searcher.Search(query, (Filter)null, n);
  137. if (docs == null || docs.TotalHits == 0)
  138. {
  139. return null;
  140. }
  141. else
  142. {
  143. List<MySearchUnit> list = new List<MySearchUnit>();
  144. int counter = 1;
  145. foreach (ScoreDoc sd in docs.ScoreDocs)//遍历搜索到的结果
  146. {
  147. try
  148. {
  149. Document doc = searcher.Doc(sd.Doc);
  150. string id = doc.Get("id");
  151. string title = doc.Get("title");
  152. string content = doc.Get("content");
  153. string flag = doc.Get("flag");
  154. string imageurl = doc.Get("imageurl");
  155. string updatetime = doc.Get("updatetime");
  156. string createdate = doc.Get("createdate");
  157. PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>");
  158. PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new PanGu.Segment());
  159. highlighter.FragmentSize = 50;
  160. content = highlighter.GetBestFragment(keyword, content);
  161. string titlehighlight = highlighter.GetBestFragment(keyword, title);
  162. if (titlehighlight != "") title = titlehighlight;
  163. list.Add(new MySearchUnit(id, title, content, flag,imageurl, updatetime));
  164. }
  165. catch (Exception ex)
  166. {
  167. Console.WriteLine(ex.Message);
  168. }
  169. counter++;
  170. }
  171. return list;
  172. }
  173. //st.Stop();
  174. //Response.Write("查询时间:" + st.ElapsedMilliseconds + " 毫秒<br/>");
  175. }
  176. #endregion
  177. #region 在不同的分类下再根据title和content字段中查询数据(分页)
  178. /// <summary>
  179. /// 在不同的类型下再根据title和content字段中查询数据(分页)
  180. /// </summary>
  181. /// <param name="_flag">分类,传空值查询全部</param>
  182. /// <param name="keyword"></param>
  183. /// <param name="PageIndex"></param>
  184. /// <param name="PageSize"></param>
  185. /// <param name="TotalCount"></param>
  186. /// <returns></returns>
  187. public List<MySearchUnit> Search(string _flag,string keyword, int PageIndex, int PageSize, out int TotalCount)
  188. {
  189. if (PageIndex < 1) PageIndex = 1;
  190. //Stopwatch st = new Stopwatch();
  191. //st.Start();
  192. BooleanQuery bq = new BooleanQuery();
  193. if (_flag != "")
  194. {
  195. QueryParser qpflag = new QueryParser(version, "flag", analyzer);
  196. Query qflag = qpflag.Parse(_flag);
  197. bq.Add(qflag, Occur.MUST);//与运算
  198. }
  199. if (keyword != "")
  200. {
  201. string[] fileds = { "title", "content" };//查询字段
  202. QueryParser parser = null;// new QueryParser(version, field, analyzer);//一个字段查询
  203. parser = new MultiFieldQueryParser(version, fileds, analyzer);//多个字段查询
  204. Query queryKeyword = parser.Parse(keyword);
  205. bq.Add(queryKeyword, Occur.MUST);//与运算
  206. }
  207. TopScoreDocCollector collector = TopScoreDocCollector.Create(PageIndex * PageSize, false);
  208. IndexSearcher searcher = new IndexSearcher(directory_luce, true);//true-表示只读
  209. searcher.Search(bq, collector);
  210. if (collector == null || collector.TotalHits == 0)
  211. {
  212. TotalCount = 0;
  213. return null;
  214. }
  215. else
  216. {
  217. int start = PageSize * (PageIndex - 1);
  218. //结束数
  219. int limit = PageSize;
  220. ScoreDoc[] hits = collector.TopDocs(start, limit).ScoreDocs;
  221. List<MySearchUnit> list = new List<MySearchUnit>();
  222. int counter = 1;
  223. TotalCount = collector.TotalHits;
  224. foreach (ScoreDoc sd in hits)//遍历搜索到的结果
  225. {
  226. try
  227. {
  228. Document doc = searcher.Doc(sd.Doc);
  229. string id = doc.Get("id");
  230. string title = doc.Get("title");
  231. string content = doc.Get("content");
  232. string flag = doc.Get("flag");
  233. string imageurl = doc.Get("imageurl");
  234. string updatetime = doc.Get("updatetime");
  235. PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>");
  236. PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new PanGu.Segment());
  237. highlighter.FragmentSize = 50;
  238. content = highlighter.GetBestFragment(keyword, content);
  239. string titlehighlight = highlighter.GetBestFragment(keyword, title);
  240. if (titlehighlight != "") title = titlehighlight;
  241. list.Add(new MySearchUnit(id, title, content, flag,imageurl, updatetime));
  242. }
  243. catch (Exception ex)
  244. {
  245. Console.WriteLine(ex.Message);
  246. }
  247. counter++;
  248. }
  249. return list;
  250. }
  251. //st.Stop();
  252. //Response.Write("查询时间:" + st.ElapsedMilliseconds + " 毫秒<br/>");
  253. }
  254. #endregion
  255. #region 删除索引数据(根据id)
  256. /// <summary>
  257. /// 删除索引数据(根据id)
  258. /// </summary>
  259. /// <param name="id"></param>
  260. /// <returns></returns>
  261. public bool Delete(string id)
  262. {
  263. bool IsSuccess = false;
  264. Term term = new Term("id", id);
  265. //Analyzer analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
  266. //Version version = new Version();
  267. //MultiFieldQueryParser parser = new MultiFieldQueryParser(version, new string[] { "name", "job" }, analyzer);//多个字段查询
  268. //Query query = parser.Parse("小王");
  269. //IndexReader reader = IndexReader.Open(directory_luce, false);
  270. //reader.DeleteDocuments(term);
  271. //Response.Write("删除记录结果: " + reader.HasDeletions + "<br/>");
  272. //reader.Dispose();
  273. IndexWriter writer = new IndexWriter(directory_luce, analyzer, false, IndexWriter.MaxFieldLength.LIMITED);
  274. writer.DeleteDocuments(term); // writer.DeleteDocuments(term)或者writer.DeleteDocuments(query);
  275. ////writer.DeleteAll();
  276. writer.Commit();
  277. //writer.Optimize();//
  278. IsSuccess = writer.HasDeletions();
  279. writer.Dispose();
  280. return IsSuccess;
  281. }
  282. #endregion
  283. #region 删除全部索引数据
  284. /// <summary>
  285. /// 删除全部索引数据
  286. /// </summary>
  287. /// <returns></returns>
  288. public bool DeleteAll()
  289. {
  290. bool IsSuccess = true;
  291. try
  292. {
  293. IndexWriter writer = new IndexWriter(directory_luce, analyzer, false, IndexWriter.MaxFieldLength.LIMITED);
  294. writer.DeleteAll();
  295. writer.Commit();
  296. //writer.Optimize();//
  297. IsSuccess = writer.HasDeletions();
  298. writer.Dispose();
  299. }
  300. catch
  301. {
  302. IsSuccess = false;
  303. }
  304. return IsSuccess;
  305. }
  306. #endregion
  307. #region directory_luce
  308. private Lucene.Net.Store.Directory _directory_luce = null;
  309. /// <summary>
  310. /// Lucene.Net的目录-参数
  311. /// </summary>
  312. public Lucene.Net.Store.Directory directory_luce
  313. {
  314. get
  315. {
  316. if (_directory_luce == null) _directory_luce = Lucene.Net.Store.FSDirectory.Open(directory);
  317. return _directory_luce;
  318. }
  319. }
  320. #endregion
  321. #region directory
  322. private System.IO.DirectoryInfo _directory = null;
  323. /// <summary>
  324. /// 索引在硬盘上的目录
  325. /// </summary>
  326. public System.IO.DirectoryInfo directory
  327. {
  328. get
  329. {
  330. if (_directory == null)
  331. {
  332. string dirPath = AppDomain.CurrentDomain.BaseDirectory + "SearchIndex";
  333. if (System.IO.Directory.Exists(dirPath) == false) _directory = System.IO.Directory.CreateDirectory(dirPath);
  334. else _directory = new System.IO.DirectoryInfo(dirPath);
  335. }
  336. return _directory;
  337. }
  338. }
  339. #endregion
  340. #region analyzer
  341. private Analyzer _analyzer = null;
  342. /// <summary>
  343. /// 分析器
  344. /// </summary>
  345. public Analyzer analyzer
  346. {
  347. get
  348. {
  349. //if (_analyzer == null)
  350. {
  351. _analyzer = new Lucene.Net.Analysis.PanGu.PanGuAnalyzer();//盘古分词分析器
  352. //_analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);//标准分析器
  353. }
  354. return _analyzer;
  355. }
  356. }
  357. #endregion
  358. #region version
  359. private static Lucene.Net.Util.Version _version = Lucene.Net.Util.Version.LUCENE_30;
  360. /// <summary>
  361. /// 版本号枚举类
  362. /// </summary>
  363. public Lucene.Net.Util.Version version
  364. {
  365. get
  366. {
  367. return _version;
  368. }
  369. }
  370. #endregion
  371. }
  372. #region 索引的一个行单元,相当于数据库中的一行数据
  373. /// <summary>
  374. /// 索引的一个行单元,相当于数据库中的一行数据
  375. /// </summary>
  376. public class MySearchUnit
  377. {
  378. public MySearchUnit(string _id, string _title, string _content, string _flag, string _imageurl, string _updatetime)
  379. {
  380. this.id = _id;
  381. this.title = _title;
  382. this.content = _content;
  383. this.flag = _flag;
  384. this.imageurl = _imageurl;
  385. this.updatetime = _updatetime;
  386. }
  387. /// <summary>
  388. /// 唯一的id号
  389. /// </summary>
  390. public string id { get; set; }
  391. /// <summary>
  392. /// 标题
  393. /// </summary>
  394. public string title { get; set; }
  395. /// <summary>
  396. /// 内容
  397. /// </summary>
  398. public string content { get; set; }
  399. /// <summary>
  400. /// 其他信息
  401. /// </summary>
  402. public string flag { get; set; }
  403. /// <summary>
  404. /// 图片路径
  405. /// </summary>
  406. public string imageurl { get; set; }
  407. /// <summary>
  408. /// 时间
  409. /// </summary>
  410. public string updatetime { get; set; }
  411. }
  412. #endregion
  413. }


//调用测试


  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. //PanGuLuceneHelper.instance.DeleteAll();//删除全部
  4. //PanGuLuceneHelper.instance.Delete("1d");//根据id删除
  5. bool exec = false;
  6. if (exec)
  7. {
  8. List<MySearchUnit> list = new List<MySearchUnit>();
  9. list.Add(new MySearchUnit("1a", "标题小王", "今天是小王的生日,大家都很高兴去他家喝酒,玩了一整天。", new Random().Next(1, 10).ToString(), "", ""));
  10. list.Add(new MySearchUnit("1b", "标题小张", "今天是小张的生日,大家都很高兴去他家喝酒,玩了几天。", new Random().Next(1, 10).ToString(), "", ""));
  11. list.Add(new MySearchUnit("1c", "标题小王", "今天是小王的生日,大家都很高兴去他家喝酒,玩了一整天。", new Random().Next(1, 10).ToString(), "", ""));
  12. list.Add(new MySearchUnit("1d", "标题小张", "今天是小张的生日,大家都很高兴去他家喝酒,玩了几天。", new Random().Next(1, 10).ToString(), "", ""));
  13. PanGuLuceneHelper.instance.CreateIndex(list);//添加索引
  14. }
  15. int count = 0;
  16. int PageIndex=2;
  17. int PageSize=4;
  18. string html_content = "";
  19. List<MySearchUnit> searchlist = PanGuLuceneHelper.instance.Search("3","小王 生日",PageIndex,PageSize,out count);
  20. html_content+=("查询结果:" + count + "条数据<br/>");
  21. if (searchlist == null || searchlist.Count==0)
  22. {
  23. html_content += ("未查询到数据。<br/>");
  24. }
  25. else
  26. {
  27. foreach (MySearchUnit data in searchlist)
  28. {
  29. html_content += (string.Format("id:{0},title:{1},content:{2},flag:{3},updatetime:{4}<br/>", data.id, data.title, data.content, data.flag, data.updatetime));
  30. }
  31. }
  32. html_content += (PanGuLuceneHelper.instance.version);
  33. div_content.InnerHtml = html_content;
  34. }


//效果:

第一版源码示例下载:http://download.csdn.net/detail/pukuimin1226/6768179

最新源码示例下载:http://download.csdn.net/detail/pukuimin1226/6776049

百度云盘下载链接:http://pan.baidu.com/s/1o69cCD8

Lucene.Net没有判断数据重复性,同一条数据插入多少遍它就有多少条相同的数据,所以,我们人为地用id区分,在数据量大,全部重新创建索引时间长的情况下(数据量到几万以上就耗资源了,从数据库中查询出来,再写入索引,使得数据库和程序本身都增加负担),增量建立索引是很有必要的。

新增一条数据,就直接添加一条索引;

修改一条数据,先删除同一个id的索引(不管有多少个id相同的,都会一次性删除),再添加一条。

数据库中的id建议大家都用guid去掉“-”,还可以加日期“yyyyMMddHHmmss”这样组合,长度一致看起来美观,也充分保证唯一。

lucene.net 3.0.3、结合盘古分词进行搜索的小例子(分页功能)的更多相关文章

  1. lucene.net helper类 【结合盘古分词进行搜索的小例子(分页功能)】

      转自:http://blog.csdn.net/pukuimin1226/article/details/17558247 添加:2013-12-25 更新:2013-12-26 新增分页功能. ...

  2. lucene.net 3.0.3、结合盘古分词进行搜索的小例子(转)

    lucene.net 3.0.3.结合盘古分词进行搜索的小例子(分页功能)   添加:2013-12-25 更新:2013-12-26 新增分页功能. 更新:2013-12-27 新增按分类查询功能, ...

  3. Lucene.net入门学习(结合盘古分词)

    Lucene简介 Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整 ...

  4. Lucene.net入门学习(结合盘古分词)(转载)

    作者:释迦苦僧  出处:http://www.cnblogs.com/woxpp/p/3972233.html  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显 ...

  5. 使用Lucene.net+盘古分词实现搜索查询

    这里我的的Demo的逻辑是这样的:首先我基本的数据是储存在Sql数据库中,然后我把我的必需的数据推送到MongoDB中,这样再去利用Lucene.net+盘古创建索引:其中为什么要这样把数据推送到Mo ...

  6. 全文检索 使用最新lucene3.0.3+最新盘古分词 pangu2.4 .net 实例

    开发环境 vs2015 winform 程序 1 首先需要下载对应的DLL 文章后面统一提供程序下载地址 里面都有 2 配置pangu的参数 也可以不配置 采用默认的即可 3 创建索引,将索引存放到本 ...

  7. Lucene.Net+盘古分词->开发自己的搜索引擎

    //封装类 using System;using System.Collections.Generic;using System.Linq;using System.Web;using Lucene. ...

  8. 盘古分词修改支持mono和lucene.net3.03

    盘古分词平台兼容性 在使用Lucece.net,需要一个中文的分词组件,比较好的是盘古分词,但是我希望能够在mono的环境下运行,就使用moma检查了一下盘古分词 Assembly Version M ...

  9. 让盘古分词支持最新的Lucene.Net 3.0.3

    原文:让盘古分词支持最新的Lucene.Net 3.0.3 好多年没升级过的Lucene.Net最近居然升级了,到了3.0.3后接口发生了很大变化,原来好多分词库都不能用了,所以上次我把MMSeg给修 ...

随机推荐

  1. luogu P3393 逃离僵尸岛

    luoguP3393逃离_僵尸岛_ 一道洛谷不知道哪门子月赛的题 可以用此题来练习最短路算法 SPFA和dijkstra的练习题(关于Floyed,他死了 思路: 本题是最短路板子. 首先就是建立虚点 ...

  2. Codeforces 734C Anton and Making Potions(枚举+二分)

    题目链接:http://codeforces.com/problemset/problem/734/C 题目大意:要制作n个药,初始制作一个药的时间为x,魔力值为s,有两类咒语,第一类周瑜有m种,每种 ...

  3. peda的官方文档说明

    peda在github上的官方文档,摘抄过来,方便查阅. 安装 git clone https://github.com/longld/peda.git ~/peda echo "sourc ...

  4. hdu 1171 有num1个w1 , num2个w2 ……. (母函数)

    输入n,代表学院里面有n种设备,并且在下面输入n行,每一行输入v,m代表设备的价格为v,设备的数量是m.然后要求把这些设备的总价值分摊,尽量平分,使其总价值接近相等,最好是相等 比如样例二(1+X10 ...

  5. android练习

    package com.example.wang.testapp2; import android.app.AlertDialog; import android.content.DialogInte ...

  6. 如何让 C++ 和 C# 一样易用,而且效率更高?

    (未完成,待续..) 第一章:C++基本功 1. 养成良好的编码习惯. 2. 堆上的资源随用随还,严格控制生命周期. 第二章:一些调试心得 1. 在VisualStudio环境下,曾出现 Detect ...

  7. PHP版本--HTTP session cookie原理及应用

    PHP 的COOKIE cookie 是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制.     PHP在http 协议的头信息里发送cookie,因此  setcookie()函数必须在其它 ...

  8. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  9. JXOI2017-2018 解题报告

    链接:JXOI2017-2018 解题报告 代码预览:Github

  10. 推荐:这才是你寻寻觅觅想要的 Python 可视化神器

    Plotly Express 是一个新的高级 Python 可视化库:它是 Plotly.py 的高级封装,它为复杂的图表提供了一个简单的语法. 受 Seaborn 和 ggplot2 的启发,它专门 ...