public class Book{[Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)]public Guid Id { get; set; } [MaxLength(500)] [Display(Name = "标题")]public string Title { get; set; } [MaxLength(5000)][Display(Name = "前言")]public string Foreword { get; set; } [Display(Name = "总页数")]public int Pages { get; set; } [Display(Name = "作者")]public string Author { get; set; }}
public class AppContext:DbContext{public AppContext(){}public DbSet<Book> Books { get; set; }}ViewModels的相关:
public class SearchViewModel{public string Query { get; set; } public IEnumerable<IHit<Book>> Results { get; set; } public IDictionary<string, Suggest[]> Suggestions { get; set; } public long Elapsed { get; set; } }接下来就HomeController.cs和BooksController.cs的代码:
public class HomeController : Controller{private SearchService _searchService;public HomeController(){ _searchService = new SearchService();}public ActionResult Index(){return View();} public ActionResult Search(string query, int page = 0, int pageSize = 10){var result = _searchService.Find(query, page, pageSize); var suggestion = _searchService.FindPhraseSuggestion(query, 0, 3);var viewModel = new SearchViewModel { Query = query, Results = result.Item1,Elapsed = result.Item2, Suggestions = suggestion }; return View("Index", viewModel);} }
public class BooksController : Controller{private AppContext db = new AppContext(); public ActionResult Index(){ return View(db.Books.ToList());} public ActionResult Details(Guid? id){ if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Book book = db.Books.Find(id); if (book == null) { return HttpNotFound(); } return View(book);} public ActionResult Create(){ return View();} [HttpPost][ValidateAntiForgeryToken]public ActionResult Create([Bind(Include="Id,Title,Foreword,Pages,Author")] Book book){ if (ModelState.IsValid) { book.Id = Guid.NewGuid(); db.Books.Add(book); db.SaveChanges();//添加书 Elasticsearch.Elasticsearch.Client.Index<Book>(book);return RedirectToAction("Index"); }return View(book);} public ActionResult Edit(Guid? id){ if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Book book = db.Books.Find(id); if (book == null) { return HttpNotFound(); } return View(book);}[HttpPost][ValidateAntiForgeryToken]public ActionResult Edit([Bind(Include="Id,Title,Foreword,Pages,Author")] Book book){ if (ModelState.IsValid) { db.Entry(book).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } return View(book);} public ActionResult Delete(Guid? id){ if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Book book = db.Books.Find(id); if (book == null) { return HttpNotFound(); } return View(book);} [HttpPost, ActionName("Delete")][ValidateAntiForgeryToken]public ActionResult DeleteConfirmed(Guid id){ Book book = db.Books.Find(id); db.Books.Remove(book); db.SaveChanges(); return RedirectToAction("Index");} public JsonResult Reindex(){ foreach (var book in db.Books) { //Indexing book Elasticsearch.Elasticsearch.Client.Index<Book>(book); } return Json("OK",JsonRequestBehavior.AllowGet);} protected override void Dispose(bool disposing){ if (disposing) { db.Dispose(); } base.Dispose(disposing);}}Elasticsearch辅助类:
public class Elasticsearch{private static ElasticClient _client;public static ElasticClient Client{ get { if (_client == null) {//连接配置var setting = new ConnectionSettings(ElasticsearchConfiguration.Connection,ElasticsearchConfiguration.DefaultIndex);_client = new ElasticClient(setting); } return _client; } }}ElasticsearchConfiguration.cs类
public static class ElasticsearchConfiguration{public static string Host { get { return "http://localhost"; } } public static long Port { get { return 9200; } } public static Uri Connection{ get { return new Uri(string.Format("{0}:{1}", Host, Port)); }} public static string DefaultIndex{ get { return "library"; }}}SearchService.cs代码:
public class SearchService{public double MinScore { get {return 0.0005; }} //高亮标记前缀public string PreHighlightTag{ get { return @"<strong>"; }} //高亮标记后缀public string PostHighlightTag{ get { return @"</strong>"; }}public Tuple< IEnumerable<IHit<Book>>,long> Find(string query, int page = 0, int pageSize = 10){ var result = Elasticsearch.Elasticsearch.Client.Search<Book>(s => s .From(page * pageSize) .Size(pageSize) .MinScore(MinScore) .Highlight(h => h.PreTags(PreHighlightTag).PostTags(PostHighlightTag).OnFields(f => f.OnField(b => b.Foreword),f => f.OnField(b => b.Title))) .Query(q => q.QueryString(qs => qs.Query(query).UseDisMax())));return new Tuple<IEnumerable<IHit<Book>>, long>(result.Hits,result.ElapsedMilliseconds);} //查找短语建议public IDictionary<string, Suggest[]> FindPhraseSuggestion(string phrase, int page = 0, int pageSize = 5){ var result = Elasticsearch.Elasticsearch.Client.Search<Book>(s => s .From(page*pageSize) .Size(pageSize) .SuggestPhrase("did-you-mean", ps => ps.Text(phrase).OnField(f => f.Foreword)) .Query(q => q.MatchAll())); return result.Suggest;}public IEnumerable<IHit<Book>> FindAll(){ var result = Elasticsearch.Elasticsearch.Client.Search<Book>(s => s.AllIndices()); return result.Hits;} }Views视图
@model IEnumerable<Library.Web.Models.Book>@{ViewBag.Title = "Index";Layout = "~/Views/Shared/_Layout.cshtml"; }<h2>Index</h2><p>@Html.ActionLink("创建新书", "Create") </p> <table class="table"><tr><th> @Html.DisplayNameFor(model => model.Title)</th><th> @Html.DisplayNameFor(model => model.Foreword)</th><th> @Html.DisplayNameFor(model => model.Pages)</th><th> @Html.DisplayNameFor(model => model.Author)</th><th></th></tr>@foreach (var item in Model) {<tr><td> @Html.DisplayFor(modelItem => item.Title)</td><td> @Html.DisplayFor(modelItem => item.Foreword)</td><td> @Html.DisplayFor(modelItem => item.Pages)</td><td> @Html.DisplayFor(modelItem => item.Author)</td><td> @Html.ActionLink("编辑", "Edit", new { id=item.Id }) | @Html.ActionLink("详细", "Details", new { id=item.Id }) | @Html.ActionLink("删除", "Delete", new { id=item.Id })</td></tr> }</table>Edit.cshtml:
@model Library.Web.Models.Book@{ViewBag.Title = "Edit";Layout = "~/Views/Shared/_Layout.cshtml"; }<h2>Edit</h2> @using (Html.BeginForm()) {@Html.AntiForgeryToken() <div class="form-horizontal"><h4>Book</h4><hr />@Html.ValidationSummary(true)@Html.HiddenFor(model => model.Id) <div class="form-group"> @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div></div> <div class="form-group"> @Html.LabelFor(model => model.Foreword, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.TextAreaFor(model => model.Foreword) @Html.ValidationMessageFor(model => model.Foreword) </div></div> <div class="form-group"> @Html.LabelFor(model => model.Pages, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Pages) @Html.ValidationMessageFor(model => model.Pages) </div></div> <div class="form-group"> @Html.LabelFor(model => model.Author, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Author) @Html.ValidationMessageFor(model => model.Author) </div></div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Save" class="btn btn-default" /> </div></div></div> }<div>@Html.ActionLink("返回列表", "Index") </div>@section Scripts {@Scripts.Render("~/bundles/jqueryval") }Details.cshtml:
@model Library.Web.Models.Book@{ViewBag.Title = "Details";Layout = "~/Views/Shared/_Layout.cshtml"; }<h2>Details</h2><div><h4>Book</h4><hr /><dl class="dl-horizontal"><dt> @Html.DisplayNameFor(model => model.Title)</dt> <dd> @Html.DisplayFor(model => model.Title)</dd> <dt> @Html.DisplayNameFor(model => model.Foreword)</dt> <dd> @Html.DisplayFor(model => model.Foreword)</dd> <dt> @Html.DisplayNameFor(model => model.Pages)</dt> <dd> @Html.DisplayFor(model => model.Pages)</dd> <dt> @Html.DisplayNameFor(model => model.Author)</dt> <dd> @Html.DisplayFor(model => model.Author)</dd> </dl> </div> <p>@Html.ActionLink("编辑", "Edit", new { id = Model.Id }) |@Html.ActionLink("返回列表", "Index") </p>Delete.cshtml:
@model Library.Web.Models.Book@{ViewBag.Title = "Delete";Layout = "~/Views/Shared/_Layout.cshtml"; }<h2>Delete</h2><h3>Are you sure you want to delete this?</h3> <div><h4>Book</h4><hr /><dl class="dl-horizontal"><dt> @Html.DisplayNameFor(model => model.Title)</dt> <dd> @Html.DisplayFor(model => model.Title)</dd> <dt> @Html.DisplayNameFor(model => model.Foreword)</dt> <dd> @Html.DisplayFor(model => model.Foreword)</dd> <dt> @Html.DisplayNameFor(model => model.Pages)</dt> <dd> @Html.DisplayFor(model => model.Pages)</dd> <dt> @Html.DisplayNameFor(model => model.Author)</dt> <dd> @Html.DisplayFor(model => model.Author)</dd> </dl> @using (Html.BeginForm()) {@Html.AntiForgeryToken() <div class="form-actions no-color"> <input type="submit" value="Delete" class="btn btn-default" /> | @Html.ActionLink("返回列表", "Index")</div>} </div>Create.cshtml:
@model Library.Web.Models.Book@{ViewBag.Title = "Create";Layout = "~/Views/Shared/_Layout.cshtml"; }<h2>创建</h2> @using (Html.BeginForm()) {@Html.AntiForgeryToken() <div class="form-horizontal"><h4>Book</h4><hr />@Html.ValidationSummary(true) <div class="form-group"> @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div></div> <div class="form-group"> @Html.LabelFor(model => model.Foreword, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.TextAreaFor(model => model.Foreword) @Html.ValidationMessageFor(model => model.Foreword) </div></div> <div class="form-group"> @Html.LabelFor(model => model.Pages, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Pages) @Html.ValidationMessageFor(model => model.Pages) </div></div> <div class="form-group"> @Html.LabelFor(model => model.Author, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Author) @Html.ValidationMessageFor(model => model.Author) </div></div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="创建" class="btn btn-default" /> </div></div></div> }<div>@Html.ActionLink("回到列表", "Index") </div>@section Scripts {@Scripts.Render("~/bundles/jqueryval") }Home->Index.cshtml
@model Library.Web.ViewModels.SearchViewModel @{ViewBag.Title = "Elasticsearch"; }<div class="jumbotron"><h1>Elasticsearch入门</h1><p class="lead">安装和配置群集</p><ol><li> <a href="http://www.oracle.com/technetwork/java/ javase/downloads/index.html">安装Java</a></li><li> <a href="http://www.elasticsearch.org/ download/">安装Elasticsearch</a></li><li>运行Elasticsearch</li><li><a href="/Books/Create">增加一些书籍</a></li></ol> </div> @if (Model == null) {return; } <div style="margin-top: 30px;">@if (Model.Suggestions.Any(x => x.Key == "did-you-mean")){<span>你的意思是: </span>foreach (var suggestions in Model.Suggestions["did-you-mean"]){ var count = 0; foreach (var suggestion in suggestions.Options) { <a href="/Home/Search?query=@suggestion.Text"><strong>@suggestion.Text </strong> </a> count++; } if (count == 0) { <span class="alert-danger">没有建议!</span> } }} </div><h3><strong>Results for:</strong> @Model.Query</h3>@if (Model != null) {<table class="table table-condensed"><thead> <tr><th>文档的分数(排名相关度)</th><th>Title</th><th>Content</th><th>Author</th></tr></thead> <tbody> @foreach (var result in Model.Results) { <tr><td>@result.Score</td><td><a href="/Books/Details/@result.Id"> @if (result.Highlights != null && result.Highlights.Any(x => x.Key == "title")) { var hl = result.Highlights.FirstOrDefault(x => x.Key == "title"); foreach (var h in hl.Value.Highlights) {WriteLiteral(h); } } else { WriteLiteral(result.Source.Title); }</a></td> <td>@if (result.Highlights != null && result.Highlights.Any(x => x.Key == "foreword")){ var hl = result.Highlights.FirstOrDefault(x => x.Key == "foreword"); foreach (var h in hl.Value.Highlights) { WriteLiteral(h + "..."); }} </td> <td>@result.Source.Author</td> </tr>} @if (!Model.Results.Any()) { <tr><td colspan="4" class="alert alert-danger" style="text-align:center;">没有结果发现:(</td> </tr> }</tbody> </table><h4><span class="label label-default">@Model.Results.Count()</span>搜索结果用了 @Model.Elapsed 毫秒</h4> }_Layout.cshtml
<!DOCTYPE html> <html> <head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>@ViewBag.Title</title>@Styles.Render("~/Content/css")@Scripts.Render("~/bundles/modernizr")</head> <body><div class="navbar navbar-inverse navbar-fixed-top"><div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span> </button> @Html.ActionLink("Elasticsearch MVC示例", "Index", "Home", null, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"><li>@Html.ActionLink("Home", "Index", "Home")</li><li>@Html.ActionLink("Books", "Index", "Books")</li> </ul> @using (Html.BeginForm("Search", "Home", FormMethod.Get,new {@class = "navbar-form navbar-left"})) {<div class="form-group"><input class="form-control" type="text" placeholder="搜索" name="query" /></div><button type="submit" class="btn btn-default">提交</button> }</div> </div></div><div class="container body-content">@RenderBody()<hr /><footer> <p>© @DateTime.Now.Year - Elasticsearch, Nest, ASP.NET 应用</p></footer></div> @Scripts.Render("~/bundles/jquery")@Scripts.Render("~/bundles/bootstrap")@RenderSection("scripts", required: false) </body> </html>结果如图:
列表页
创建页:
搜索结果页:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。