public void StoreQuestion(Question question)
        {
            using (var redis = RedisManager.GetClient())
            {
                var redisQuestions = redis.As <Question>();

                if (question.Tags == null)
                {
                    question.Tags = new List <string>();
                }
                if (question.Id == default(long))
                {
                    question.Id          = redisQuestions.GetNextSequence();
                    question.CreatedDate = DateTime.UtcNow;

                    //Increment the popularity for each new question tag
                    question.Tags.ForEach(tag => redis.IncrementItemInSortedSet(TagIndex.All, tag, 1));
                }

                redisQuestions.Store(question);
                redisQuestions.AddToRecentsList(question);
                redis.AddItemToSet(UserQuestionIndex.Questions(question.UserId), question.Id.ToString());

                //Populate tag => questions index for each tag
                question.Tags.ForEach(tag => redis.AddItemToSet(TagIndex.Questions(tag), question.Id.ToString()));
            }
        }
        /// <summary>
        /// Delete question by performing compensating actions to StoreQuestion() to keep the datastore in a consistent state
        /// </summary>
        /// <param name="questionId"></param>
        public void DeleteQuestion(long questionId)
        {
            using (var redis = RedisManager.GetClient())
            {
                var redisQuestions = redis.As <Question>();

                var question = redisQuestions.GetById(questionId);
                if (question == null)
                {
                    return;
                }

                //decrement score in tags list
                question.Tags.ForEach(tag => redis.IncrementItemInSortedSet(TagIndex.All, tag, -1));

                //remove all related answers
                redisQuestions.DeleteRelatedEntities <Answer>(questionId);

                //remove this question from user index
                redis.RemoveItemFromSet(UserQuestionIndex.Questions(question.UserId), questionId.ToString());

                //remove tag => questions index for each tag
                question.Tags.ForEach(tag => redis.RemoveItemFromSet(TagIndex.Questions(tag), questionId.ToString()));

                redisQuestions.DeleteById(questionId);
            }
        }
        public List <QuestionResult> GetQuestionsByUser(long userId)
        {
            using var redis = RedisManager.GetReadOnlyClient();
            var questionIds = redis.GetAllItemsFromSet(UserQuestionIndex.Questions(userId));
            var questions   = redis.As <Question>().GetByIds(questionIds);

            return(ToQuestionResults(questions));
        }
 public UserStat GetUserStats(long userId)
 {
     using var redis = RedisManager.GetClient();
     return(new UserStat
     {
         UserId = userId,
         QuestionsCount = redis.GetSetCount(UserQuestionIndex.Questions(userId)),
         AnswersCount = redis.GetSetCount(UserAnswerIndex.Answers(userId)),
     });
 }
        public void VoteQuestionDown(long userId, long questionId)
        {
            //Populate Question => User and User => Question set indexes in a single transaction
            RedisManager.ExecTrans(trans =>
            {
                //Register downvote against question and remove any upvotes if any
                trans.QueueCommand(redis => redis.AddItemToSet(QuestionUserIndex.DownVotes(questionId), userId.ToString()));
                trans.QueueCommand(redis => redis.RemoveItemFromSet(QuestionUserIndex.UpVotes(questionId), userId.ToString()));

                //Register downvote against user and remove any upvotes if any
                trans.QueueCommand(redis => redis.AddItemToSet(UserQuestionIndex.DownVotes(userId), questionId.ToString()));
                trans.QueueCommand(redis => redis.RemoveItemFromSet(UserQuestionIndex.UpVotes(userId), questionId.ToString()));
            });
        }