AdvertisementService.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. using CacheManager.Core;
  2. using EFCoreSecondLevelCacheInterceptor;
  3. using Masuit.LuceneEFCore.SearchEngine.Interfaces;
  4. using Masuit.MyBlogs.Core.Common;
  5. using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
  6. using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
  7. using Masuit.MyBlogs.Core.Models.Entity;
  8. using Masuit.MyBlogs.Core.Models.Enum;
  9. using Masuit.Tools;
  10. using Masuit.Tools.Linq;
  11. using System.Linq.Expressions;
  12. using System.Text.RegularExpressions;
  13. using Microsoft.EntityFrameworkCore;
  14. namespace Masuit.MyBlogs.Core.Infrastructure.Services
  15. {
  16. public partial class AdvertisementService : BaseService<Advertisement>, IAdvertisementService
  17. {
  18. public ICacheManager<List<Advertisement>> CacheManager { get; set; }
  19. public ICategoryRepository CategoryRepository { get; set; }
  20. private readonly ILuceneIndexSearcher _luceneIndexSearcher;
  21. public AdvertisementService(IBaseRepository<Advertisement> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
  22. {
  23. _luceneIndexSearcher = searcher;
  24. }
  25. /// <summary>
  26. /// 按价格随机筛选一个元素
  27. /// </summary>
  28. /// <param name="type">广告类型</param>
  29. /// <param name="location"></param>
  30. /// <param name="cid">分类id</param>
  31. /// <param name="keywords"></param>
  32. /// <returns></returns>
  33. public Advertisement GetByWeightedPrice(AdvertiseType type, IPLocation location, int? cid = null, string keywords = "")
  34. {
  35. return GetsByWeightedPrice(1, type, location, cid, keywords).FirstOrDefault();
  36. }
  37. /// <summary>
  38. /// 按价格随机筛选一个元素
  39. /// </summary>
  40. /// <param name="count">数量</param>
  41. /// <param name="type">广告类型</param>
  42. /// <param name="ipinfo"></param>
  43. /// <param name="cid">分类id</param>
  44. /// <param name="keywords"></param>
  45. /// <returns></returns>
  46. public List<Advertisement> GetsByWeightedPrice(int count, AdvertiseType type, IPLocation ipinfo, int? cid = null, string keywords = "")
  47. {
  48. var (location, _, _) = ipinfo;
  49. return CacheManager.GetOrAdd($"Advertisement:{location.Crc32()}:{type}:{count}-{cid}-{keywords}", _ =>
  50. {
  51. var atype = type.ToString("D");
  52. Expression<Func<Advertisement, bool>> where = a => a.Types.Contains(atype) && a.Status == Status.Available;
  53. var catCount = CategoryRepository.Count(_ => true);
  54. where = where.And(a => a.RegionMode == RegionLimitMode.All || (a.RegionMode == RegionLimitMode.AllowRegion ? Regex.IsMatch(location, a.Regions) : !Regex.IsMatch(location, a.Regions)));
  55. if (cid.HasValue)
  56. {
  57. var pids = CategoryRepository.GetQuery(c => c.Id == cid).Select(c => c.ParentId + "|" + c.Parent.ParentId).Cacheable().ToArray();
  58. var scid = pids.Select(s => s.Trim('|')).Where(s => !string.IsNullOrEmpty(s)).Append(cid + "").Join("|");
  59. if (Any(a => Regex.IsMatch(a.CategoryIds, scid)))
  60. {
  61. where = where.And(a => Regex.IsMatch(a.CategoryIds, scid) || string.IsNullOrEmpty(a.CategoryIds));
  62. }
  63. }
  64. if (!keywords.IsNullOrEmpty())
  65. {
  66. var regex = _luceneIndexSearcher.CutKeywords(keywords).Select(Regex.Escape).Join("|");
  67. where = where.And(a => Regex.IsMatch(a.Title + a.Description, regex));
  68. }
  69. var list = GetQuery(where).OrderBy(a => -Math.Log(EF.Functions.Random()) / ((double)a.Price / a.Types.Length * catCount / (string.IsNullOrEmpty(a.CategoryIds) ? catCount : (a.CategoryIds.Length + 1)))).Take(count).ToList();
  70. if (list.Count == 0 && keywords is { Length: > 0 })
  71. {
  72. return GetsByWeightedPrice(count, type, ipinfo, cid);
  73. }
  74. var ids = list.Select(a => a.Id).ToArray();
  75. GetQuery(a => ids.Contains(a.Id)).UpdateFromQuery(a => new Advertisement
  76. {
  77. DisplayCount = a.DisplayCount + 1
  78. });
  79. return list;
  80. });
  81. }
  82. }
  83. }