[C#]
/// <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.什麼條件也不給,顯示全部
2.按日期查詢