Explorar el Código

今日热榜性能优化

懒得勤快 hace 3 años
padre
commit
aecc6eb30c

+ 10 - 9
src/Masuit.MyBlogs.Core/Controllers/HomeController.cs

@@ -85,10 +85,10 @@ namespace Masuit.MyBlogs.Core.Controllers
         {
             var viewModel = await GetIndexPageViewModel();
             var postsQuery = PostService.GetQuery(PostBaseWhere().And(p => p.Status == Status.Published)); //准备文章的查询
-            var h24 = DateTime.Now.AddDays(-1);
+            var h24 = DateTime.Today.AddDays(-1);
             var posts = orderBy switch
             {
-                OrderBy.Trending => await postsQuery.Where(p => !p.IsFixedTop).OrderByDescending(p => p.PostVisitRecords.Count(e => e.Time >= h24)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
+                OrderBy.Trending => await postsQuery.Where(p => !p.IsFixedTop).OrderByDescending(p => p.PostVisitRecordStats.Where(e => e.Date >= h24).Sum(t => t.Count)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
                 _ => await postsQuery.Where(p => !p.IsFixedTop).OrderBy((orderBy ?? OrderBy.ModifyDate).GetDisplay() + " desc").ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig)
             };
             if (page == 1)
@@ -126,10 +126,10 @@ namespace Masuit.MyBlogs.Core.Controllers
 
             var where = PostBaseWhere().And(p => p.Status == Status.Published);
             var queryable = PostService.GetQuery(tag.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).Aggregate(where, (current, s) => current.And(p => Regex.IsMatch(p.Label, s))));
-            var h24 = DateTime.Now.AddDays(-1);
+            var h24 = DateTime.Today.AddDays(-1);
             var posts = orderBy switch
             {
-                OrderBy.Trending => await queryable.OrderByDescending(p => p.PostVisitRecords.Count(e => e.Time >= h24)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
+                OrderBy.Trending => await queryable.OrderByDescending(p => p.PostVisitRecordStats.Where(e => e.Date >= h24).Sum(e => e.Count)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
                 _ => await queryable.OrderBy($"{nameof(PostDto.IsFixedTop)} desc,{(orderBy ?? OrderBy.ModifyDate).GetDisplay()} desc").ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig)
             };
             var viewModel = await GetIndexPageViewModel();
@@ -159,10 +159,10 @@ namespace Masuit.MyBlogs.Core.Controllers
         {
             Expression<Func<Post, bool>> where = p => p.Author.Equals(author) || p.Modifier.Equals(author) || p.Email.Equals(author) || p.PostHistoryVersion.Any(v => v.Modifier.Equals(author) || v.ModifierEmail.Equals(author));
             where = where.And(p => p.Status == Status.Published).And(PostBaseWhere());
-            var h24 = DateTime.Now.AddDays(-1);
+            var h24 = DateTime.Today.AddDays(-1);
             var posts = orderBy switch
             {
-                OrderBy.Trending => await PostService.GetQuery(where).OrderByDescending(p => p.PostVisitRecords.Count(e => e.Time >= h24)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
+                OrderBy.Trending => await PostService.GetQuery(where).OrderByDescending(p => p.PostVisitRecordStats.Where(e => e.Date >= h24).Sum(e => e.Count)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
                 _ => await PostService.GetQuery(where).OrderBy($"{nameof(PostDto.IsFixedTop)} desc,{(orderBy ?? OrderBy.ModifyDate).GetDisplay()} desc").ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig)
             };
             var viewModel = await GetIndexPageViewModel();
@@ -191,10 +191,10 @@ namespace Masuit.MyBlogs.Core.Controllers
         public async Task<ActionResult> Category(int id, [Optional] OrderBy? orderBy, [Range(1, int.MaxValue, ErrorMessage = "页码必须大于0")] int page = 1, [Range(1, 50, ErrorMessage = "页大小必须在0到50之间")] int size = 15)
         {
             var cat = await CategoryService.GetByIdAsync(id) ?? throw new NotFoundException("文章分类未找到");
-            var h24 = DateTime.Now.AddDays(-1);
+            var h24 = DateTime.Today.AddDays(-1);
             var posts = orderBy switch
             {
-                OrderBy.Trending => await PostService.GetQuery(PostBaseWhere().And(p => p.CategoryId == cat.Id && p.Status == Status.Published)).OrderByDescending(p => p.PostVisitRecords.Count(e => e.Time >= h24)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
+                OrderBy.Trending => await PostService.GetQuery(PostBaseWhere().And(p => p.CategoryId == cat.Id && p.Status == Status.Published)).OrderByDescending(p => p.PostVisitRecordStats.Where(e => e.Date >= h24).Sum(e => e.Count)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
                 _ => await PostService.GetQuery(PostBaseWhere().And(p => p.CategoryId == cat.Id && p.Status == Status.Published)).OrderBy($"{nameof(PostDto.IsFixedTop)} desc,{(orderBy ?? OrderBy.ModifyDate).GetDisplay()} desc").ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig)
             };
             var viewModel = await GetIndexPageViewModel();
@@ -244,6 +244,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                 {
                     case "txt":
                         return Content((await fs.ReadAllLinesAsync(Encoding.UTF8)).Select(s => Request.Scheme + "://" + Request.Host.Host + new Uri(s).GetComponents(UriComponents.PathAndQuery, UriFormat.UriEscaped)).Join("\r\n"), ContentType.Txt);
+
                     case "html":
                         var context = BrowsingContext.New(Configuration.Default);
                         var doc = await context.OpenAsync(req => req.Content(fs.ReadAllText(Encoding.UTF8)));
@@ -288,4 +289,4 @@ namespace Masuit.MyBlogs.Core.Controllers
             };
         }
     }
-}
+}

+ 4 - 4
src/Masuit.MyBlogs.Core/Controllers/PostController.cs

@@ -1015,13 +1015,13 @@ namespace Masuit.MyBlogs.Core.Controllers
                 Title = p.Title,
                 ViewCount = (int)p.AverageViewCount
             }).Cacheable().ToListAsync();
-            var h24 = DateTime.Now.AddDays(-1);
-            var trending = await postsQuery.OrderByDescending(p => p.PostVisitRecords.Count(e => e.Time >= h24)).Take(10).Select(p => new PostModelBase()
+            var h24 = DateTime.Today.AddDays(-1);
+            var trending = await postsQuery.Select(p => new PostModelBase()
             {
                 Id = p.Id,
                 Title = p.Title,
-                ViewCount = p.PostVisitRecords.Count(e => e.Time >= h24)
-            }).Cacheable().ToListAsync();
+                ViewCount = p.PostVisitRecordStats.Where(t => t.Date >= h24).Sum(e => e.Count)
+            }).OrderByDescending(p => p.ViewCount).Take(10).Cacheable().ToListAsync();
             return ResultData(new
             {
                 mostHots,

+ 5 - 4
src/Masuit.MyBlogs.Core/Controllers/SeminarController.cs

@@ -44,10 +44,10 @@ namespace Masuit.MyBlogs.Core.Controllers
         public async Task<ActionResult> Index(int id, [Optional] OrderBy? orderBy, [Range(1, int.MaxValue, ErrorMessage = "页码必须大于0")] int page = 1, [Range(1, 50, ErrorMessage = "页大小必须在0到50之间")] int size = 15)
         {
             var s = await SeminarService.GetByIdAsync(id) ?? throw new NotFoundException("专题未找到");
-            var h24 = DateTime.Now.AddDays(-1);
+            var h24 = DateTime.Today.AddDays(-1);
             var posts = orderBy switch
             {
-                OrderBy.Trending => await PostService.GetQuery(PostBaseWhere().And(p => p.Seminar.Any(x => x.Id == id) && p.Status == Status.Published)).OrderByDescending(p => p.PostVisitRecords.Count(e => e.Time >= h24)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
+                OrderBy.Trending => await PostService.GetQuery(PostBaseWhere().And(p => p.Seminar.Any(x => x.Id == id) && p.Status == Status.Published)).OrderByDescending(p => p.PostVisitRecordStats.Where(e => e.Date >= h24).Sum(e => e.Count)).ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig),
                 _ => await PostService.GetQuery(PostBaseWhere().And(p => p.Seminar.Any(x => x.Id == id) && p.Status == Status.Published)).OrderBy($"{nameof(Post.IsFixedTop)} desc,{(orderBy ?? OrderBy.ModifyDate).GetDisplay()} desc").ToCachedPagedListAsync<Post, PostDto>(page, size, MapperConfig)
             };
             ViewBag.Id = s.Id;
@@ -172,12 +172,13 @@ namespace Masuit.MyBlogs.Core.Controllers
         {
             Seminar seminar = await SeminarService.GetByIdAsync(id);
             Post post = await PostService.GetByIdAsync(pid);
+
             //bool b = await seminarPostService.DeleteEntitySavedAsync(s => s.SeminarId == id && s.PostId == pid) > 0;
             seminar.Post.Remove(post);
             var b = await SeminarService.SaveChangesAsync() > 0;
             return ResultData(null, b, b ? $"已成功将【{post.Title}】从专题【{seminar.Title}】移除" : "添加失败!");
         }
 
-        #endregion
+        #endregion 管理端
     }
-}
+}

+ 19 - 2
src/Masuit.MyBlogs.Core/Extensions/Hangfire/HangfireBackJob.cs

@@ -27,6 +27,7 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         private readonly IAdvertisementService _advertisementService;
         private readonly INoticeService _noticeService;
         private readonly IPostVisitRecordService _recordService;
+        private readonly IPostVisitRecordStatsService _recordStatsService;
 
         /// <summary>
         /// hangfire后台任务
@@ -39,7 +40,7 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         /// <param name="httpClientFactory"></param>
         /// <param name="HostEnvironment"></param>
         /// <param name="searchEngine"></param>
-        public HangfireBackJob(IUserInfoService userInfoService, IPostService postService, ISystemSettingService settingService, ISearchDetailsService searchDetailsService, ILinksService linksService, IHttpClientFactory httpClientFactory, IWebHostEnvironment HostEnvironment, ISearchEngine<DataContext> searchEngine, IAdvertisementService advertisementService, INoticeService noticeService, ILinkLoopbackService loopbackService, IPostVisitRecordService recordService)
+        public HangfireBackJob(IUserInfoService userInfoService, IPostService postService, ISystemSettingService settingService, ISearchDetailsService searchDetailsService, ILinksService linksService, IHttpClientFactory httpClientFactory, IWebHostEnvironment HostEnvironment, ISearchEngine<DataContext> searchEngine, IAdvertisementService advertisementService, INoticeService noticeService, ILinkLoopbackService loopbackService, IPostVisitRecordService recordService, IPostVisitRecordStatsService recordStatsService)
         {
             _userInfoService = userInfoService;
             _postService = postService;
@@ -53,6 +54,7 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
             _noticeService = noticeService;
             _loopbackService = loopbackService;
             _recordService = recordService;
+            _recordStatsService = recordStatsService;
         }
 
         /// <summary>
@@ -111,11 +113,11 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         /// <param name="ip"></param>
         /// <param name="refer"></param>
         /// <param name="url"></param>
-        /// <param name="headers"></param>
         public void RecordPostVisit(int pid, string ip, string refer, string url)
         {
             var time = DateTime.Now.AddMonths(-3);
             _recordService.GetQuery(b => b.Time < time).DeleteFromQuery();
+            _recordStatsService.GetQuery(b => b.Date < time).DeleteFromQuery();
             var post = _postService.GetById(pid);
             if (post == null)
             {
@@ -133,6 +135,21 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
                 RequestUrl = url,
                 PostId = pid
             });
+            var stats = _recordStatsService.Get(e => e.PostId == pid && e.Date >= DateTime.Today);
+            if (stats != null)
+            {
+                stats.Count++;
+            }
+            else
+            {
+                _recordStatsService.AddEntity(new PostVisitRecordStats()
+                {
+                    Count = 1,
+                    Date = DateTime.Today,
+                    PostId = pid
+                });
+            }
+
             _postService.SaveChanges();
         }
 

+ 2 - 2
src/Masuit.MyBlogs.Core/Extensions/TranslateMiddleware.cs

@@ -51,7 +51,7 @@ namespace Masuit.MyBlogs.Core.Extensions
 
         private async Task Traditional(HttpContext context)
         {
-            var accept = context.Request.Headers["Accept"][0];
+            var accept = context.Request.Headers["Accept"].ToString();
             if (accept.StartsWith("text") || accept.Contains(ContentType.Json))
             {
                 //设置stream存放ResponseBody
@@ -76,4 +76,4 @@ namespace Masuit.MyBlogs.Core.Extensions
             }
         }
     }
-}
+}

+ 1 - 0
src/Masuit.MyBlogs.Core/Infrastructure/DataContext.cs

@@ -25,6 +25,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure
             modelBuilder.Entity<Post>().HasMany(e => e.Seminar).WithMany(s => s.Post).UsingEntity(builder => builder.ToTable("SeminarPost"));
             modelBuilder.Entity<Post>().HasMany(e => e.PostMergeRequests).WithOne(s => s.Post).HasForeignKey(r => r.PostId).OnDelete(DeleteBehavior.Cascade);
             modelBuilder.Entity<Post>().HasMany(e => e.PostVisitRecords).WithOne().HasForeignKey(r => r.PostId).OnDelete(DeleteBehavior.Cascade);
+            modelBuilder.Entity<Post>().HasMany(e => e.PostVisitRecordStats).WithOne().HasForeignKey(r => r.PostId).OnDelete(DeleteBehavior.Cascade);
             modelBuilder.Entity<PostHistoryVersion>().HasMany(e => e.Seminar).WithMany(s => s.PostHistoryVersion).UsingEntity(builder => builder.ToTable("SeminarPostHistoryVersion"));
 
             modelBuilder.Entity<UserInfo>().HasMany(e => e.LoginRecord).WithOne(e => e.UserInfo).OnDelete(DeleteBehavior.Cascade);

+ 3 - 0
src/Masuit.MyBlogs.Core/Infrastructure/Repository/Interface/IBaseRepository.cs

@@ -712,4 +712,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository.Interface
 
     public partial interface IPostVisitRecordRepository : IBaseRepository<PostVisitRecord>
     { }
+
+    public partial interface IPostVisitRecordStatsRepository : IBaseRepository<PostVisitRecordStats>
+    { }
 }

+ 14 - 0
src/Masuit.MyBlogs.Core/Infrastructure/Repository/Repositories.cs

@@ -282,4 +282,18 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
             return t;
         }
     }
+
+    public partial class PostVisitRecordStatsRepository : BaseRepository<PostVisitRecordStats>, IPostVisitRecordStatsRepository
+    {
+        /// <summary>
+        /// 添加实体
+        /// </summary>
+        /// <param name="t">需要添加的实体</param>
+        /// <returns>添加成功</returns>
+        public override PostVisitRecordStats AddEntity(PostVisitRecordStats t)
+        {
+            DataContext.Add(t);
+            return t;
+        }
+    }
 }

+ 3 - 0
src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IServices.cs

@@ -44,6 +44,9 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
     public partial interface IPostVisitRecordService : IBaseService<PostVisitRecord>
     { }
 
+    public partial interface IPostVisitRecordStatsService : IBaseService<PostVisitRecordStats>
+    { }
+
     public partial interface IAdvertisementClickRecordService : IBaseService<AdvertisementClickRecord>
     { }
 }

+ 7 - 0
src/Masuit.MyBlogs.Core/Infrastructure/Services/Services.cs

@@ -103,6 +103,13 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         }
     }
 
+    public partial class PostVisitRecordStatsService : BaseService<PostVisitRecordStats>, IPostVisitRecordStatsService
+    {
+        public PostVisitRecordStatsService(IBaseRepository<PostVisitRecordStats> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
+        {
+        }
+    }
+
     public partial class AdvertisementClickRecordService : BaseService<AdvertisementClickRecord>, IAdvertisementClickRecordService
     {
         public AdvertisementClickRecordService(IBaseRepository<AdvertisementClickRecord> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)

+ 2 - 2
src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.csproj

@@ -44,7 +44,7 @@
         <PackageReference Include="CacheManager.StackExchange.Redis" Version="1.2.0" />
         <PackageReference Include="CHTCHSConv" Version="1.0.0" />
         <PackageReference Include="CLRStats" Version="1.0.0" />
-        <PackageReference Include="CSRedisCore" Version="3.6.6" />
+        <PackageReference Include="CSRedisCore" Version="3.6.8" />
         <PackageReference Include="EFCoreSecondLevelCacheInterceptor" Version="3.2.4" />
         <PackageReference Include="Hangfire" Version="1.7.27" />
         <PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
@@ -56,7 +56,7 @@
         <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.1" />
         <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="6.0.1" />
         <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="6.0.1" />
-        <PackageReference Include="Microsoft.Graph" Version="4.11.0" />
+        <PackageReference Include="Microsoft.Graph" Version="4.12.0" />
         <PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.7" />
         <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
         <PackageReference Include="OpenXmlPowerTools-NetStandard" Version="4.4.21" />

+ 5 - 0
src/Masuit.MyBlogs.Core/Models/Entity/Post.cs

@@ -208,6 +208,11 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// ·ÃÎʼǼ
         /// </summary>
         public virtual ICollection<PostVisitRecord> PostVisitRecords { get; set; }
+
+        /// <summary>
+        /// ·ÃÎʼǼͳ¼Æ
+        /// </summary>
+        public virtual ICollection<PostVisitRecordStats> PostVisitRecordStats { get; set; }
     }
 
     /// <summary>

+ 16 - 0
src/Masuit.MyBlogs.Core/Models/Entity/PostVisitRecordStats.cs

@@ -0,0 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Masuit.MyBlogs.Core.Models.Entity;
+
+[Table("PostVisitRecordStats")]
+public class PostVisitRecordStats : BaseEntity
+{
+    public int PostId { get; set; }
+
+    [ConcurrencyCheck]
+    public DateTime Date { get; set; }
+
+    [ConcurrencyCheck]
+    public int Count { get; set; }
+}