Эффективно ограничивая результат пересечения между двумя наборами в Redis - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть система программного обеспечения для сдачи экзамена, и одна из функций - показывать студентам случайные вопросы из огромного набора, учитывая, что этот вопрос никогда раньше не показывался студенту. Я использую Redis для его реализации, поэтому я сделал два набора типов в моей базе данных Redis, первый - это банк вопросов, а затем у каждого пользователя есть свой набор ранее просмотренных вопросов, который обновляется после того, как пользователь видит вопрос в экзамен.

Однако, чтобы выполнить требование, мне нужно найти 10 вопросов из банка вопросов для каждого экзамена, который пользователь никогда раньше не видел. Я подумал об использовании:

SDIFFSTORE nextQuestionsToShow questionBank userQuestionsSet
SRANDMEMBER nextQuestionsToShow 10

и после обработки результата удаляю полученный набор nextQuestionsToShow.

Однако я думаю, что это неэффективно (по времени и памяти), поскольку это всегда система онлайн-экзаменов для пользователей в течение дня, и в банке вопросов имеется огромное количество вопросов по категориям (в некоторых категориях более 100 тыс. вопросов), и это означает, что разница - это огромный набор для каждого пользователя, который должен быть сохранен только для выберите 10 случайных вопросов. Так есть ли более эффективный способ выбрать 10 случайных вопросов из банка вопросов, на которые пользователь ранее не отвечал? Большое спасибо заранее.

1 Ответ

2 голосов
/ 27 апреля 2020

Вместо использования SET для хранения userQuestionsSet и questionBank, вы можете использовать растровое изображение (Redis STRING) для хранения этих двух наборов. Затем вы можете использовать BITOP, чтобы эффективно получить разницу между двумя растровыми изображениями.

ОБНОВЛЕНИЕ

Прежде всего, вам нужно дать каждому вопросу уникальный номер , Затем используйте растровое изображение для хранения userQuestionsSet и questionBank. Скажем, у вас есть следующие вопросы в банке: 1: вопрос1 , 2: вопрос2 , 3: вопрос3 , 4: вопрос4 , 5: вопрос5 . И пользователь уже просмотрел question3 :

// initialize question bank: 00111110
SETBIT question-bank 1 1
SETBIT question-bank 2 1
...
SETBIT question-bank 5 1

// user has viewed question3: 00001000
SETBIT user 3 1

Получите разницу между банком вопросов и просматриваемыми пользователем вопросами:

// XOR to get the difference: 00111110 XOR 00001000
BITOP XOR result question-bank user

// 00110110
// questions not viewed: 1, 2, 4, 5
GET result

Когда вы получаете двоичную строку, хранящуюся в В результате вы можете отсканировать строку и произвольно получить 10 вопросов для пользователя.

NOTE

Вы должны быть осторожны, так как SETBIT может быть дорогой операцией, и вам лучше заранее выделить память для этих растровых изображений. Подробности см. В разделе ПРЕДУПРЕЖДЕНИЕ do c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...