Как структурировать 1-уровневые комментарии в Redis? - PullRequest
2 голосов
/ 03 октября 2011

Я изо всех сил пытался найти структуру данных для вложенных комментариев (только 1 уровень вложенности, например, facebook)

Чтобы получить не вложенную «ленту» комментариев, я использовал отсортированные наборы для отслеживания комментариев, используя счет в качестве метки времени и члена в виде набора атрибутов в формате json, который содержит всю информацию, необходимую для визуализации. комментарий.

Поэтому добавление комментария может выглядеть так:

zadd 'users:1:comments', 123456789, {body : 'hello'}

И получить его так же просто, как это:

zrevrange 'users:1:comments', 0, 20

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

1)

Добавить comment_id в список атрибутов, где comment_id указывает на родительский комментарий

zadd 'users:1:comments', 123456789, {id : 1, body : 'hello'}
zadd 'comments:1:comments', 123456789, {id : 2, body : 'nested hello', comment_id : 123 }

будет выглядеть так:

-hello
  -nested hello

Проблема этого подхода в том, что касается нумерации страниц. Если, скажем, комментарий имеет 20 вложенных комментариев, а я показываю только первые 10 комментариев, то вложенное дерево будет обрезано (будет получен родительский комментарий + 9 вложенных комментариев)

2)

Поместите вложенные комментарии в собственный канал:

This is a parent comment
zadd 'users:1:comments', 123456789, {id: 1, body : 'hello'}
this is a nested comment
zadd 'comments:1:comments' 123456789, {id: 2, body : 'nested hello'} 

Однако это приведет к N + 1 повторным запросам при попытке показать фид пользователя:

zrevrange 'users:1:comments', 0, 20
zrevrange 'comments:1:comments', 0, 20
zrevrange 'comments:2:comments', 0, 20
etc...

... Не говоря уже о вложенных комментариях, вероятно, не следует выбирать с диапазоном.

В идеале мне бы хотелось, чтобы это работало с одним запросом redis, но я не уверен, как структурировать мои данные, чтобы это было возможно.

Идеи

1 Ответ

1 голос
/ 03 октября 2011

Единственный способ, которым я могу придумать, что приведет к одному запросу redis, - это использовать Lists .

При добавлении родительского элемента вы можете просто LPUSH поместить его вверху (слева) списка. При добавлении дочернего комментария вы должны использовать что-то вроде LINSERT 'user:1:comments' AFTER parent-comment-data child-comment-data.

Это заставляет redis искать данные родительского комментария и размещать дочерние данные сразу после них. Это операция O (N), которая выполняется сверху (слева) и снизу (справа), поэтому чем дальше вниз по списку родительский элемент, тем дольше будет выполняться эта операция, поэтому для чрезвычайно длинных списков это оказаться проблематичным (но должно подойти, если вы сохраните размер списка / резьбы в диапазоне 4 или 5 цифр).

Затем простой LRANGE может принести вам последние комментарии, как родителей, так и детей, с ограничением на любое число.

Вы можете сделать нечто подобное, используя значения баллов в отсортированных наборах, давая детям балл чуть ниже, чем у родителя. Это может значительно усложнить вставки, так как у вас могут закончиться доступные оценки между двумя родительскими комментариями, что означает, что вам придется запустить операцию, чтобы переназначить оценки для многих (или даже для большинства) комментариев. Если это происходит при каждой вставке, ваши вставки могут (без необходимости) быть дорогостоящими.

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