/// <summary>
        /// 获取指定据点的评分
        /// </summary>
        /// <param name="pointId">据点 ID</param>
        /// <exception cref="ArgumentNullException"><paramref name="pointId"/> 为 null</exception>
        /// <returns>据点评分</returns>
        public async Task <PointRatingsDto> GetRatingsAsync([NotNull] string pointId)
        {
            if (pointId == null)
            {
                throw new ArgumentNullException(nameof(pointId));
            }

            var cacheKey    = RatingCacheKey(pointId);
            var redisDb     = _redis.GetDatabase();
            var cacheResult = await redisDb.StringGetAsync(cacheKey);

            if (cacheResult.HasValue)
            {
                return(RedisProvider.Deserialize <PointRatingsDto>(cacheResult));
            }

            var ratings     = new PointRatingsDto();
            var userRatings = new Dictionary <string, UserRating>();

            foreach (var ratingEntry in await _dbContext.Articles
                     .Where(a => a.TargetPointId == pointId && a.Rating != null &&
                            a.Archived == ArchivedState.None && a.Rejected == false)
                     .Select(a => new { a.AuthorId, a.Rating })
                     .Union(_dbContext.Activities
                            .Where(a => a.TargetPointId == pointId && a.Rating != null)
                            .Select(a => new { a.AuthorId, a.Rating }))
                     .ToListAsync())
            {
                switch (ratingEntry.Rating.Value)
                {
                case 1:
                    ratings.OneStarCount++;
                    break;

                case 2:
                    ratings.TwoStarCount++;
                    break;

                case 3:
                    ratings.ThreeStarCount++;
                    break;

                case 4:
                    ratings.FourStarCount++;
                    break;

                case 5:
                    ratings.FiveStarCount++;
                    break;

                default:
                    continue;
                }
                UserRating userRating;
                if (!userRatings.TryGetValue(ratingEntry.AuthorId, out userRating))
                {
                    userRatings[ratingEntry.AuthorId] = userRating = new UserRating();
                }
                userRating.Count++;
                userRating.Total += ratingEntry.Rating.Value;
            }
            ratings.AverageRating = userRatings.Count < 3
                ? (double?)null
                : Math.Round(userRatings.Values.Sum(r => r.Total * 2 / (double)r.Count) / userRatings.Count, 1);
            await redisDb.StringSetAsync(cacheKey, RedisProvider.Serialize(ratings), RatingUpdatePeriod);

            return(ratings);
        }