/// <summary> /// 搜索 /// </summary> /// <param name="k"></param> /// <param name="cid"></param> /// <returns></returns> public ActionResult Search(string k, string p, DateTime? startDate, DateTime? endDate) { Stopwatch st = new Stopwatch(); st.Start();//计时开始 //为索引存储目录 string INDEX_STORE_PATH = Server.MapPath("~/SearchIndex"); var ver = Lucene.Net.Util.Version.LUCENE_29; Directory indexDirectory = FSDirectory.Open(new System.IO.DirectoryInfo(INDEX_STORE_PATH)); Analyzer analyzer = new StandardAnalyzer(ver); IndexSearcher searcher = null; List<Article> list; int recCount = 0; bool isk = !string.IsNullOrEmpty(k), isp = !string.IsNullOrEmpty(p), isstartdate = startDate.HasValue, isenddate = endDate.HasValue; try { searcher = new IndexSearcher(indexDirectory, true); BooleanQuery booleanQuery = new BooleanQuery(); /* * 多字段查询同时搜索title和summary */ //string[] fields = { "title", "summary" }; //MultiFieldQueryParser parser = new MultiFieldQueryParser(ver, fields, analyzer); //Query query = parser.Parse(k); //Query query1 = new QueryParser(ver, "classid", analyzer).Parse("1"); /* * TermQuery搜索文档的最小单位 * 如果不分词索引,只能整体都符合才能命中 * 如classname以不分词的形式索引 * classname="体育新闻" * 你只搜体育或新闻是不能命中的,只有收体育新闻才能命中 * TermQuery适合用来搜索Id,classname之类的索引 */ //Query query1 = new TermQuery(new Term("id", "1")); //Query query2 = new TermQuery(new Term("classname", k)); /* * QueryParser支持分词索引支持类似sql语句的查询等, * 搜索形式是把你输入的关键字先分词,分词之后再拿来搜索 * 当然由于自带的StandardAnalyzer对中文分词不怎么好, * (经测试StandardAnalyzer对中文的分词不会一空格来分词) * 我们就拿英文搜索来说吧。 * 例如我们输入的关键字为 I love you * 他会先把I love you 分词 可能 分成 I/love/you/i love/ i love you/具体怎么分大家可以试试看 * 然后再拿来搜索,如果你的文档中存在 i 或者 love 或者you都会命中 * 注意:使用QueryParser的搜索当k为Empty或null时会报错注意处理 */ //查询关键字 if (isk) { Query query3 = new QueryParser(ver, "title", analyzer).Parse(k); booleanQuery.Add(query3, BooleanClause.Occur.MUST); } /* * NumericRangeQuery按范围搜索,前提是搜索的字段必须是以NumericField文档索引 * NumericRangeQuery可以对数字、日期、时间进行范围搜索 * 对日期和时间搜索时,先把日期转成数字存索引,查询时也是把日期转成数字再查询, * 但是此种方法日期转换比较麻烦 */ //按价格范围搜索(对数字搜索) if (isp) { string[] prices = p.Split(new char[] { '_' }); float min = float.Parse(prices[0]); float max = prices.Length < 2 ? 10000000000.00f : float.Parse(prices[1]); Query query4 = NumericRangeQuery.NewFloatRange("price", min, max, true, true); booleanQuery.Add(query4, BooleanClause.Occur.MUST); } /* * TermRangeQuery具体什么原理还不那么明白,有待研究 */ //按日期范围搜索(对日期搜索) if (isstartdate || isenddate) { string mindate = isstartdate ? startDate.Value.ToString("yyyy-MM-dd") : DateTime.MinValue.ToString("yyyy-MM-dd"); string maxdate = isenddate ? endDate.Value.ToString("yyyy-MM-dd") : DateTime.Today.ToString("yyyy-MM-dd"); Query query5 = new TermRangeQuery("createtime", mindate, maxdate, true, true); booleanQuery.Add(query5, BooleanClause.Occur.MUST); } //如果没有查询关键字则显示全部的数据 if (!isk && !isp && !isstartdate && !isenddate) { Query query6 = new TermQuery(new Term("all", "all")); booleanQuery.Add(query6, BooleanClause.Occur.MUST); } //执行搜索,获取查询结果集对象 TopDocs ts = searcher.Search(booleanQuery, null, 100); //ts = searcher.MaxDoc(); recCount = ts.totalHits;//获取命中的文档个数 ScoreDoc[] hits = ts.scoreDocs;//获取命中的文档信息对象 st.Stop();//计时停止 ViewBag.EvenTime = string.Format("{0}毫秒,生成的Query语句:{1}", st.ElapsedMilliseconds, booleanQuery.ToString()); ViewBag.Count = recCount; list = new List<Article>(); foreach (var item in hits) { list.Add(new Article() { Id = searcher.Doc(item.doc).Get("id"), ClassId = searcher.Doc(item.doc).Get("classid"), ClassName = searcher.Doc(item.doc).Get("classname"), Title = searcher.Doc(item.doc).Get("title"), Price = float.Parse(searcher.Doc(item.doc).Get("price")), //Summary = searcher.Doc(item.doc).Get("summary"), Score = item.score.ToString(), CreateTime = Convert.ToDateTime(searcher.Doc(item.doc).Get("createtime")) }); } } catch (Exception) { throw; } finally { if (searcher != null) { searcher.Close(); } } return View(list); }
最后效果:
1.什么条件也不给,显示全部