Elasticsearch.Net使用教程 MVC4图书管理系统(2)
作者:天风隼
这篇文章主要介绍了Elasticsearch.Net使用教程教会大家利用MVC4制作图书管理系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了MVC4图书管理系统的制作教程,供大家参考,具体内容如下
首先项目结构图:
Model层的相关代码如下:
Book.cs代码如下:
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辅助类:
首先是Elasticsearch.cs
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视图
Books文件夹下:
Index.cshtml:
@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>
结果如图:
列表页
创建页:
搜索结果页:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。