Elasticsearch.Net使用教程 MVC4图书管理系统(2)

时间:2022-02-13 13:22:14

本文实例为大家分享了MVC4图书管理系统的制作教程,供大家参考,具体内容如下

首先项目结构图:

Elasticsearch.Net使用教程 MVC4图书管理系统(2)

Model层的相关代码如下:
Book.cs代码如下:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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; }
 }
 
?
1
 
2
3
4
5
6
7
8
public class AppContext:DbContext
 {
 public AppContext()
 {
  
 }
 public DbSet<Book> Books { get; set; }
 }

ViewModels的相关:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
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的代码:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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);
 }
 
 }
 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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类

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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代码:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@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:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
@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:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@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:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@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:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
@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

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
@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

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!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>

结果如图:

Elasticsearch.Net使用教程 MVC4图书管理系统(2)

列表页

Elasticsearch.Net使用教程 MVC4图书管理系统(2)

创建页:

Elasticsearch.Net使用教程 MVC4图书管理系统(2)

搜索结果页:

Elasticsearch.Net使用教程 MVC4图书管理系统(2)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。