SearchController.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using Common;
  2. using Masuit.LuceneEFCore.SearchEngine.Interfaces;
  3. using Masuit.MyBlogs.Core.Extensions;
  4. using Masuit.MyBlogs.Core.Infrastructure.Application;
  5. using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
  6. using Masuit.MyBlogs.Core.Models.DTO;
  7. using Masuit.MyBlogs.Core.Models.Entity;
  8. using Masuit.Tools;
  9. using Masuit.Tools.Core.Net;
  10. using Masuit.Tools.NoSQL;
  11. using Microsoft.AspNetCore.Mvc;
  12. using Microsoft.Net.Http.Headers;
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Linq;
  16. using System.Linq.Expressions;
  17. using System.Text.RegularExpressions;
  18. namespace Masuit.MyBlogs.Core.Controllers
  19. {
  20. /// <summary>
  21. /// 站内搜索
  22. /// </summary>
  23. public class SearchController : BaseController
  24. {
  25. /// <summary>
  26. ///
  27. /// </summary>
  28. public ISearchDetailsService SearchDetailsService { get; set; }
  29. private readonly IPostService _postService;
  30. private readonly ISearchEngine<DataContext> _searchEngine;
  31. /// <summary>
  32. /// 站内搜索
  33. /// </summary>
  34. /// <param name="searchDetailsService"></param>
  35. /// <param name="postService"></param>
  36. /// <param name="searchEngine"></param>
  37. public SearchController(ISearchDetailsService searchDetailsService, IPostService postService, ISearchEngine<DataContext> searchEngine)
  38. {
  39. SearchDetailsService = searchDetailsService;
  40. _postService = postService;
  41. _searchEngine = searchEngine;
  42. }
  43. /// <summary>
  44. /// 搜索页
  45. /// </summary>
  46. /// <param name="wd"></param>
  47. /// <param name="page"></param>
  48. /// <param name="size"></param>
  49. /// <returns></returns>
  50. [Route("s/{wd?}/{page:int?}/{size:int?}"), ResponseCache(VaryByQueryKeys = new[] { "wd", "page", "size" }, VaryByHeader = HeaderNames.Cookie, Duration = 60)]
  51. public ActionResult Search(string wd = "", int page = 1, int size = 10)
  52. {
  53. var nul = new List<PostOutputDto>();
  54. ViewBag.Elapsed = 0;
  55. ViewBag.Total = 0;
  56. ViewBag.Keyword = wd ?? "";
  57. if (Regex.Match(wd, CommonHelper.BanRegex).Length > 0 || Regex.Match(wd, CommonHelper.ModRegex).Length > 0)
  58. {
  59. //ViewBag.Wd = "";
  60. return RedirectToAction("Search");
  61. }
  62. var start = DateTime.Today.AddDays(-7);
  63. using (RedisHelper redisHelper = RedisHelper.GetInstance())
  64. {
  65. string key = HttpContext.Connection.Id;
  66. if (redisHelper.KeyExists(key) && !redisHelper.GetString(key).Equals(wd))
  67. {
  68. var hotSearches = SearchDetailsService.LoadEntitiesFromL2CacheNoTracking(s => s.SearchTime > start, s => s.SearchTime, false).GroupBy(s => s.KeyWords.ToLower()).OrderByDescending(g => g.Count()).Take(7).Select(g => new KeywordsRankOutputDto()
  69. {
  70. KeyWords = g.First().KeyWords,
  71. SearchCount = g.Count()
  72. }).ToList();
  73. ViewBag.hotSearches = hotSearches;
  74. ViewBag.ErrorMsg = "10秒内只能搜索1次!";
  75. return View(nul);
  76. }
  77. wd = wd.Trim().Replace("+", " ");
  78. if (!string.IsNullOrWhiteSpace(wd) && !wd.Contains("锟斤拷"))
  79. {
  80. if (!HttpContext.Session.TryGetValue("search:" + wd, out _))
  81. {
  82. SearchDetailsService.AddEntity(new SearchDetails
  83. {
  84. KeyWords = wd,
  85. SearchTime = DateTime.Now,
  86. IP = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString()
  87. });
  88. HttpContext.Session.Set("search:" + wd, wd);
  89. }
  90. var posts = _postService.SearchPage(page, size, wd);
  91. ViewBag.Elapsed = posts.Elapsed;
  92. ViewBag.Total = posts.Total;
  93. SearchDetailsService.SaveChanges();
  94. if (posts.Total > 1)
  95. {
  96. redisHelper.SetString(key, wd, TimeSpan.FromSeconds(10));
  97. }
  98. ViewBag.hotSearches = new List<KeywordsRankOutputDto>();
  99. return View(posts.Results);
  100. }
  101. ViewBag.hotSearches = SearchDetailsService.LoadEntitiesFromL2CacheNoTracking(s => s.SearchTime > start, s => s.SearchTime, false).GroupBy(s => s.KeyWords.ToLower()).OrderByDescending(g => g.Count()).Take(7).Select(g => new KeywordsRankOutputDto()
  102. {
  103. KeyWords = g.FirstOrDefault().KeyWords,
  104. SearchCount = g.Count()
  105. }).ToList();
  106. return View(nul);
  107. }
  108. }
  109. /// <summary>
  110. /// 关键词推荐
  111. /// </summary>
  112. /// <param name="page"></param>
  113. /// <param name="size"></param>
  114. /// <param name="search"></param>
  115. /// <returns></returns>
  116. [Authority, HttpPost, ResponseCache(Duration = 600, VaryByQueryKeys = new[] { "page", "size", "search" }, VaryByHeader = HeaderNames.Cookie)]
  117. public ActionResult SearchList(int page = 1, int size = 10, string search = "")
  118. {
  119. if (page <= 0)
  120. {
  121. page = 1;
  122. }
  123. var where = string.IsNullOrEmpty(search) ? (Expression<Func<SearchDetails, bool>>)(s => true) : s => s.KeyWords.Contains(search);
  124. var list = SearchDetailsService.LoadPageEntities<DateTime, SearchDetailsOutputDto>(page, size, out int total, where, s => s.SearchTime, false).ToList();
  125. var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
  126. return PageResult(list, pageCount, total);
  127. }
  128. /// <summary>
  129. /// 热词
  130. /// </summary>
  131. /// <returns></returns>
  132. [Authority, HttpPost, ResponseCache(Duration = 600, VaryByHeader = HeaderNames.Cookie)]
  133. public ActionResult HotKey()
  134. {
  135. var start = DateTime.Today.AddMonths(-1);
  136. var temp = SearchDetailsService.LoadEntitiesNoTracking(s => s.SearchTime > start, s => s.SearchTime, false).ToList();
  137. var month = temp.GroupBy(s => s.KeyWords.ToLower()).OrderByDescending(g => g.Count()).Take(30).Select(g => new
  138. {
  139. Keywords = g.FirstOrDefault().KeyWords,
  140. Count = g.Count()
  141. }).ToList();
  142. var week = temp.Where(s => s.SearchTime > DateTime.Today.AddDays(-7)).GroupBy(s => s.KeyWords.ToLower()).OrderByDescending(g => g.Count()).Take(30).Select(g => new
  143. {
  144. Keywords = g.FirstOrDefault().KeyWords,
  145. Count = g.Count()
  146. }).ToList();
  147. var today = temp.Where(s => s.SearchTime > DateTime.Today).GroupBy(s => s.KeyWords.ToLower()).OrderByDescending(g => g.Count()).Take(30).Select(g => new
  148. {
  149. Keywords = g.FirstOrDefault().KeyWords,
  150. Count = g.Count()
  151. }).ToList();
  152. return ResultData(new
  153. {
  154. month,
  155. week,
  156. today
  157. });
  158. }
  159. /// <summary>
  160. /// 删除搜索记录
  161. /// </summary>
  162. /// <param name="id"></param>
  163. /// <returns></returns>
  164. [HttpPost, Authority]
  165. public ActionResult Delete(int id)
  166. {
  167. bool b = SearchDetailsService.DeleteByIdSaved(id);
  168. return ResultData(null, b, b ? "删除成功!" : "删除失败!");
  169. }
  170. }
  171. }