Lucene.NET使用入门(二)【简单的搜索网站示例】
来源:互联网 发布:天龙八部九阴神爪 知 编辑:程序博客网 时间:2024/05/17 07:54
项目结构:
LuceneSearch.Data层
SampleData.cs
namespace LuceneSearch.Model { public class SampleData { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } }}
SelectedList.cs
namespace LuceneSearch.Model { public class SelectedList { public string Value { get; set; } public string Text { get; set; } }}
SampleDataRepository.cs
using System.Collections.Generic;using System.Linq;using LuceneSearch.Model;namespace LuceneSearch.Repository{ public static class SampleDataRepository { public static SampleData Get(int id) { return GetAll().SingleOrDefault(x => x.Id.Equals(id)); } public static List<SampleData> GetAll() { return new List<SampleData> { new SampleData {Id = 1, Name = "Belgrad", Description = "City in Serbia"}, new SampleData {Id = 2, Name = "Moscow", Description = "City in Russia"}, new SampleData {Id = 3, Name = "Chicago", Description = "City in USA"}, new SampleData {Id = 4, Name = "Mumbai", Description = "City in India"}, new SampleData {Id = 5, Name = "Hong-Kong", Description = "City in Hong-Kong"}, }; } }}
LuceneSearch.Library层
GoLucene.cs
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Web;using Lucene.Net.Analysis.Standard;using Lucene.Net.Documents;using Lucene.Net.Index;using Lucene.Net.QueryParsers;using Lucene.Net.Search;using Lucene.Net.Store;using LuceneSearch.Model;using Version = Lucene.Net.Util.Version;namespace LuceneSearch.Service{ public static class GoLucene { // 属性 public static string _luceneDir =Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, "lucene_index"); private static FSDirectory _directoryTemp; private static FSDirectory _directory { get { if (_directoryTemp == null) _directoryTemp = FSDirectory.Open(new DirectoryInfo(_luceneDir)); if (IndexWriter.IsLocked(_directoryTemp)) IndexWriter.Unlock(_directoryTemp); var lockFilePath = Path.Combine(_luceneDir, "write.lock"); if (File.Exists(lockFilePath)) File.Delete(lockFilePath); return _directoryTemp; } } // 搜索方法 public static IEnumerable<SampleData> GetAllIndexRecords() { // 验证搜索索引 if (!System.IO.Directory.EnumerateFiles(_luceneDir).Any()) return new List<SampleData>(); // 设置lucene搜索器 var searcher = new IndexSearcher(_directory, false); var reader = IndexReader.Open(_directory, false); var docs = new List<Document>(); var term = reader.TermDocs(); // v 2.9.4: use 'term.Doc()' // v 3.0.3: use 'term.Doc' while (term.Next()) docs.Add(searcher.Doc(term.Doc)); reader.Dispose(); searcher.Dispose(); return _mapLuceneToDataList(docs); } public static IEnumerable<SampleData> Search(string input, string fieldName = "") { if (string.IsNullOrEmpty(input)) return new List<SampleData>(); var terms = input.Trim().Replace("-", " ").Split(' ') .Where(x => !string.IsNullOrEmpty(x)).Select(x => x.Trim() + "*"); input = string.Join(" ", terms); return _search(input, fieldName); } public static IEnumerable<SampleData> SearchDefault(string input, string fieldName = "") { return string.IsNullOrEmpty(input) ? new List<SampleData>() : _search(input, fieldName); } // 主要搜索方法 private static IEnumerable<SampleData> _search(string searchQuery, string searchField = "") { // 验证 if (string.IsNullOrEmpty(searchQuery.Replace("*", "").Replace("?", ""))) return new List<SampleData>(); // 设置Lucene搜索器 using (var searcher = new IndexSearcher(_directory, false)) { var hits_limit = 1000; var analyzer = new StandardAnalyzer(Version.LUCENE_30); // 搜索单字段 if (!string.IsNullOrEmpty(searchField)) { var parser = new QueryParser(Version.LUCENE_30, searchField, analyzer); var query = parseQuery(searchQuery, parser); var hits = searcher.Search(query, hits_limit).ScoreDocs; var results = _mapLuceneToDataList(hits, searcher); analyzer.Close(); searcher.Dispose(); return results; } // 搜索多个字段(按照RELEVANCE排序) else { var parser = new MultiFieldQueryParser (Version.LUCENE_30, new[] { "Id", "Name", "Description" }, analyzer); var query = parseQuery(searchQuery, parser); var hits = searcher.Search(query, null, hits_limit, Sort.INDEXORDER).ScoreDocs; var results = _mapLuceneToDataList(hits, searcher); analyzer.Close(); searcher.Dispose(); return results; } } } private static Query parseQuery(string searchQuery, QueryParser parser) { Query query; try { query = parser.Parse(searchQuery.Trim()); } catch (ParseException) { query = parser.Parse(QueryParser.Escape(searchQuery.Trim())); } return query; } // 将Lucene搜索索引映射到数据 private static IEnumerable<SampleData> _mapLuceneToDataList(IEnumerable<Document> hits) { return hits.Select(_mapLuceneDocumentToData).ToList(); } private static IEnumerable<SampleData> _mapLuceneToDataList(IEnumerable<ScoreDoc> hits, IndexSearcher searcher) { // v 2.9.4: use 'hit.doc' // v 3.0.3: use 'hit.Doc' return hits.Select(hit => _mapLuceneDocumentToData(searcher.Doc(hit.Doc))).ToList(); } private static SampleData _mapLuceneDocumentToData(Document doc) { return new SampleData { Id = Convert.ToInt32(doc.Get("Id")), Name = doc.Get("Name"), Description = doc.Get("Description") }; } // 添加/更新/清除 搜索索引数据 public static void AddUpdateLuceneIndex(SampleData sampleData) { AddUpdateLuceneIndex(new List<SampleData> { sampleData }); } public static void AddUpdateLuceneIndex(IEnumerable<SampleData> sampleDatas) { // 初始lucene var analyzer = new StandardAnalyzer(Version.LUCENE_30); using (var writer = new IndexWriter(_directory, analyzer, IndexWriter.MaxFieldLength.UNLIMITED)) { // add data to lucene search index (replaces older entries if any) //将数据添加到lucene搜索索引(如果有的话替换旧条目) foreach (var sampleData in sampleDatas) _addToLuceneIndex(sampleData, writer); // 关闭 analyzer.Close(); writer.Dispose(); } } public static void ClearLuceneIndexRecord(int record_id) { // 初始lucene var analyzer = new StandardAnalyzer(Version.LUCENE_30); using (var writer = new IndexWriter(_directory, analyzer, IndexWriter.MaxFieldLength.UNLIMITED)) { // 删除旧索引条目 var searchQuery = new TermQuery(new Term("Id", record_id.ToString())); writer.DeleteDocuments(searchQuery); // 关闭 analyzer.Close(); writer.Dispose(); } } public static bool ClearLuceneIndex() { try { var analyzer = new StandardAnalyzer(Version.LUCENE_30); using (var writer = new IndexWriter(_directory, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED)) { // 删除旧索引条目 writer.DeleteAll(); // 关闭 analyzer.Close(); writer.Dispose(); } } catch (Exception) { return false; } return true; } public static void Optimize() { var analyzer = new StandardAnalyzer(Version.LUCENE_30); using (var writer = new IndexWriter(_directory, analyzer, IndexWriter.MaxFieldLength.UNLIMITED)) { analyzer.Close(); writer.Optimize(); writer.Dispose(); } } private static void _addToLuceneIndex(SampleData sampleData, IndexWriter writer) { // 删除旧索引条目 var searchQuery = new TermQuery(new Term("Id", sampleData.Id.ToString())); writer.DeleteDocuments(searchQuery); // 添加新的索引条目 var doc = new Document(); // 添加映射到db字段的lucene字段 doc.Add(new Field("Id", sampleData.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("Name", sampleData.Name, Field.Store.YES, Field.Index.ANALYZED)); doc.Add(new Field("Description", sampleData.Description, Field.Store.YES, Field.Index.ANALYZED)); // 添加条目到索引 writer.AddDocument(doc); } }}
LuceneSearch.Mvc层
HomeController.cs
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Web.Mvc;using LuceneSearch.Repository;using LuceneSearch.Service;using LuceneSearch.Model;using MvcLuceneSampleApp.ViewModels;namespace MvcLuceneSampleApp.Controllers{ public class HomeController : Controller { public ActionResult Index(string searchTerm, string searchField, bool? searchDefault, int? limit) { //创建默认的Lucene搜索索引目录 if (!Directory.Exists(GoLucene._luceneDir)) { Directory.CreateDirectory(GoLucene._luceneDir); } //执行Lucene搜索 List<SampleData> _searchResults; if (searchDefault == true) { _searchResults = (string.IsNullOrEmpty(searchField) ? GoLucene.SearchDefault(searchTerm) : GoLucene.SearchDefault(searchTerm, searchField)).ToList(); } else { _searchResults = (string.IsNullOrEmpty(searchField) ? GoLucene.Search(searchTerm) : GoLucene.Search(searchTerm, searchField)).ToList(); } if (string.IsNullOrEmpty(searchTerm) && !_searchResults.Any()) { _searchResults = GoLucene.GetAllIndexRecords().ToList(); } //设置和返回视图模型 var search_field_list = new List<SelectedList> { new SelectedList {Text = "(所有字段)", Value = ""}, new SelectedList {Text = "Id", Value = "Id"}, new SelectedList {Text = "Name", Value = "Name"}, new SelectedList {Text = "Description", Value = "Description"} }; //限制显示数据库记录数 var limitDb = limit == null ? 3 : Convert.ToInt32(limit); List<SampleData> allSampleData; if (limitDb > 0) { allSampleData = SampleDataRepository.GetAll().ToList().Take(limitDb).ToList(); ViewBag.Limit = SampleDataRepository.GetAll().Count - limitDb; } else allSampleData = SampleDataRepository.GetAll(); return View(new IndexViewModel { AllSampleData = allSampleData, SearchIndexData = _searchResults, SampleData = new SampleData { Id = 9, Name = "埃尔帕索", Description = "德克萨斯城市" }, SearchFieldList = search_field_list, }); } public ActionResult Search(string searchTerm, string searchField, string searchDefault) { return RedirectToAction("Index", new { searchTerm, searchField, searchDefault }); } public ActionResult CreateIndex() { GoLucene.AddUpdateLuceneIndex(SampleDataRepository.GetAll()); TempData["Result"] = "搜索索引已成功创建!"; return RedirectToAction("Index"); } [HttpPost] public ActionResult AddToIndex(SampleData sampleData) { GoLucene.AddUpdateLuceneIndex(sampleData); TempData["Result"] = "记录被成功添加到搜索索引!"; return RedirectToAction("Index"); } public ActionResult ClearIndex() { if (GoLucene.ClearLuceneIndex()) TempData["Result"] = "搜索索引已成功清除!"; else TempData["ResultFail"] = "索引已锁定,无法清除,请稍后重试或手动清除!"; return RedirectToAction("Index"); } public ActionResult ClearIndexRecord(int id) { GoLucene.ClearLuceneIndexRecord(id); TempData["Result"] = "搜索索引记录已成功删除!"; return RedirectToAction("Index"); } public ActionResult OptimizeIndex() { GoLucene.Optimize(); TempData["Result"] = "搜索索引成功优化!"; return RedirectToAction("Index"); } }}
IndexViewModel.cs
using System.Collections.Generic;using LuceneSearch.Model;namespace MvcLuceneSampleApp.ViewModels{ public class IndexViewModel { public int Limit { get; set; } public bool SearchDefault { get; set; } public SampleData SampleData { get; set; } public IEnumerable<SampleData> AllSampleData { get; set; } public IEnumerable<SampleData> SearchIndexData { get; set; } public IList<SelectedList> SearchFieldList { get; set; } public string SearchTerm { get; set; } public string SearchField { get; set; } }}
Index.cshtml
@model MvcLuceneSampleApp.ViewModels.IndexViewModel<div class="content_left"> <span style="color: green;">@TempData["Result"]</span> <span style="color: red;">@TempData["ResultFail"]</span></div><div class="clear"></div><div class="col_12"> <fieldset> <legend>数据库记录 (@Html.ActionLink("从数据库创建搜索索引 [+]", "CreateIndex"))</legend> <table class="grid"> <tr> <th>@Html.LabelFor(m => Model.SampleData.Id)</th> <th>@Html.LabelFor(m => Model.SampleData.Name)</th> <th>@Html.LabelFor(m => Model.SampleData.Description)</th> </tr> @foreach (var record in Model.AllSampleData) { <tr> <td>@record.Id</td> <td>@record.Name</td> <td>@record.Description</td> </tr> } </table> @if (ViewBag.Limit > 0) { <div class="margin_top10"> <b>@ViewBag.Limit</b> 条更多记录... (<a href="\?limit=0">查看全部</a>)</div> } </fieldset></div><div class="col_12"> <fieldset> <legend>搜索(自定义,适用于大多数基本场景)</legend> <div class="content_left margin_top5"> <p>尝试这些搜索: <em>"1 3 5", "City", "Russia India", "bel mos ind"</em></p> </div> @using (Html.BeginForm("Search", "Home")) { <div class="content_left margin_top13 margin_left30"> @Html.CheckBoxFor(m => m.SearchDefault) @Html.LabelFor(m => m.SearchDefault, "使用默认的Lucene查询") </div> <div class="content_left margin_right20"> @Html.TextBoxFor(m => m.SearchTerm, new { @class = "big", style = "width:650px;", autocomplete = "off" }) </div> <div class="content_left margin_top15 margin_right30"> @Html.DropDownListFor(m => m.SearchField, Model.SearchFieldList.Select(x => new SelectListItem { Text = x.Text, Value = x.Value }), new { style = "width:150px;" }) </div> <div class="content_right margin_top8"> <input type="submit" value="搜索" /> </div> <div class="clear"></div> } </fieldset></div><div class="col_8"> <fieldset> <legend> Search index (@Html.ActionLink("优化", "OptimizeIndex")) (@Html.ActionLink("清除 [X]", "ClearIndex")) </legend> @if (Model.SearchIndexData.Any()) { <table class="grid"> <tr> <th>@Html.LabelFor(m => Model.SampleData.Id)</th> <th>@Html.LabelFor(m => Model.SampleData.Name)</th> <th>@Html.LabelFor(m => Model.SampleData.Description)</th> <th></th> </tr> @foreach (var record in Model.SearchIndexData) { <tr> <td>@record.Id</td> <td>@record.Name</td> <td>@record.Description</td> <td>@Html.ActionLink("删除", "ClearIndexRecord", new { record.Id })</td> </tr> } </table> } else { <text><br />找不到搜索索引记录...<br /></text> } </fieldset></div><div class="col_4"> <fieldset class="add_record"> <legend>添加/更新 搜索索引记录</legend> 使用现有的ID进行更新 @using (Html.BeginForm("AddToIndex", "Home")) { <div class="form_horizontal"> <p> @Html.LabelFor(m => m.SampleData.Id)<br /> @Html.TextBoxFor(m => m.SampleData.Id, new { style = "width:30px;" }) </p> <p> @Html.LabelFor(m => m.SampleData.Name)<br /> @Html.TextBoxFor(m => m.SampleData.Name, new { style = "width:100px;" }) </p> <p> @Html.LabelFor(m => m.SampleData.Description)<br /> @Html.TextBoxFor(m => m.SampleData.Description, new { style = "width:120px;" }) </p> </div> <div class="clear"></div> <input type="submit" value="添加/更新 记录" /> } </fieldset></div><script type="text/javascript"> $(document).ready(function () { $('#SearchTerm').focus(); $('.grid tr:even').css("background", "silver"); });</script>
_Layout.cshtml
@{ Layout = null;}<!DOCTYPE html><html><head> <title>Lucene.Net | MVC</title> <link href="@Url.Content("~/Content/style.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/kickstart/kickstart.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/style.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/style.lib.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/style.local.css")" rel="stylesheet" type="text/css" /> <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script> <script type="text/javascript">window.jQuery || document.write('<script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")"><\/script>')</script> <script src="@Url.Content("~/Scripts/kickstart.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/prettify.js")" type="text/javascript"></script></head><body> <div class="header clearfix"> <div class="top_menu"><a href="/">主页</a></div> <h2>Lucene.Net for MVC => 创建更容易!</h2> <h3>简单的Lucene.Net使用示例站点</h3> </div> <div class="content clearfix"> @RenderBody() </div> <div class="footer">© @DateTime.Now.Year </div></body></html>
_Layout.cshtml
@{ Layout = null;}<!DOCTYPE html><html><head> <title>Lucene.Net | MVC</title> <link href="@Url.Content("~/Content/style.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/kickstart/kickstart.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/style.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/style.lib.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/style.local.css")" rel="stylesheet" type="text/css" /> <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script> <script type="text/javascript">window.jQuery || document.write('<script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")"><\/script>')</script> <script src="@Url.Content("~/Scripts/kickstart.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/prettify.js")" type="text/javascript"></script></head><body> <div class="header clearfix"> <div class="top_menu"><a href="/">主页</a></div> <h2>Lucene.Net for MVC => 创建更容易!</h2> <h3>简单的Lucene.Net使用示例站点</h3> </div> <div class="content clearfix"> @RenderBody() </div> <div class="footer"> © @DateTime.Now.Year </div></body></html>
运行结果如图:
阅读全文
0 0
- Lucene.NET使用入门(二)【简单的搜索网站示例】
- lucene入门-简单的WEB搜索界面
- c#使用Lucene.net创建索引,实现搜索的代码示例
- Lucene.NET使用入门(一)【实现快速搜索】
- [lucene]使用lucene建立网站搜索服务
- 用Lucene.net建立自己的网站搜索
- 用Lucene.net建立自己的网站搜索
- Lucene.net全文搜索示例Demo
- Lucene使用(二)示例
- Lucene-搜索的入门例子
- lucene搜索简单的实例
- 原来lucene如此简单(二)搜索
- lucene搜索 代码示例
- lucene.net的使用
- 使用Lucene.net 实现全文搜索
- 使用Lucene.net技术,仿百度搜索
- Lucene的简单使用
- Lucene的简单使用
- 【NOIP普及组2016】&魔法阵 This is magic!&
- springMVC之mvc:interceptors拦截器的用法
- 学习心得
- selenium开发环境部署Maven官方依赖porm文件分享
- 编码与Python逻辑运算
- Lucene.NET使用入门(二)【简单的搜索网站示例】
- vue中的所有axios请求都会发送2次,但是第一次不返回数据的原因
- RabbitMQ消息队列(一): Detailed Introduction 详细介绍
- 学习心得
- OSGI中Command -控制台命令
- 文件操作
- 前端工程化之路:初探 Sass 技术
- linux下搭建搭建svn服务器
- 399. Evaluate Division