powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Проектирование френдленты и рейтингов
4 сообщений из 4, страница 1 из 1
Проектирование френдленты и рейтингов
    #36604252
ViktorSemenov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Есть сайт с:
- пользователями (Users: UID, UserName)
- у пользователей есть посты (Posts: PID, UID, Content)
- у постов есть комментарии (Comments: CID, PID, UID, CommentContent).
- друзья пользователей (Friends: UID, FriendUID)

Далее каждый пользователь может оценивать как посты, так и комментарии (обычные +/- ).
Так же, пользователь может добавлять других пользователей в друзья.

Хочу спросить, какую структуру БД лучше всего создать для следующей задачи: хочется выводить френдленту с информацией, кто из френдов, когда и что делал (написал пост, оценил чужой пост, написал комментарий, оценил комментарий). Типо как новости вконтакте или фейсбуке.
+ хочется рейтинги постов, юзеров и комментариев вида: "лучший пост дня", "недели". Плюс сохранение истории этих рейтингов.

Проблема с пониманием того, какую структуру выбрать.
Пока придумалась одна аггрегирующая табличка активности вида:

Activity:
UID - кто сделал
TypeID - что сделал (оценил пост, оценил коммент, добавил пост, добавил коммент, ...)
ItemID - ID того, над чем произведено действие (ID поста, ID комментария)
ItemOwnerID - UID того, кто является автором поста или комментария.
RelatedItemID - ID главного элемента
RelatedItemOwnerID - UID автора главного элемента
DateOf - дата действия.
Rating - рейтинг (NULL - если запись активности не является оценкой)

RelatedItemID и RelatedItemOwnerID - это ID главных элементов (см. ниже)

Пример:
- Вася Пупкин (UID=15),
- оценил (TypeID=1) комментарий (CID=10) Феди Иванова (UID=20)
- который прокомментировал пост (PID=5) Ивана Семенова (UID=30)
- оценкой "5"
- 22 февраля 2010 года,

тогда запись в эту таблицу активности будет такой:

Код: plaintext
1.
2.
   UID  TypeID  ItemID  ItemOwnerID  RelatedItemID  RelatedItemOwnerID  DateOf       Rating  
  15       1       10       20            5                   30      22.02.2010       5

По такой таблице достаточно просто делать френдленту, ибо есть все UID'ы, и все их действия.
Но, насколько такая схема удобна и правильна?

И второй вопрос - как считать рейтинги по такой таблице?
Допустим раз в сутки я пересчитываю рейтинги каждых постов, юзеров, комментариев.
Для примера я хочу посчитать "статью дня" - статью, набравшую наибольшее кол-во голосов за 24 часа с момента её опубликования.
Дата опубликования находится как в таблице Posts (CreationDate), так и в таблице Activity
со своим TypeID. Никак не могу придумать такой запрос.
...
Рейтинг: 0 / 0
Проектирование френдленты и рейтингов
    #36606410
Леша777
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
1. Я бы в Posts добавил 2 столбца :
1) SumRating INT (суммарный рэйитг)
2) NumberOfVotes - INT (общее кол-во голосований)

При добалении поста значения полей 0, 0. При голосовании прибавляем к сумме поставленную оценку , увеливаем на 1 кол-во.

Так же добавить вычисляемый столбец. AvgRating : SumRating * 1.00 / NumberOfVotes. Желательно вычисляемый, если нет то постоянный столбец.

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

Аналогично для Comments.


Для примера я хочу посчитать "статью дня" - статью, набравшую наибольшее кол-во голосов за 24 часа с момента её опубликования.


Да , такие вещи делаются асинхронно. (В наименее загруженное время)


Зачем вам таблица Activity ? Попытка запихнуть все что только можно ?
Кем создан пост и комментарий хранятся в соответствующих таблицах и этого достаточно .
Зачем их дублировать.
Для процесса голосования добавляете 2 таблицы для постов и комментариев отдельно .
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE TABLE   PostRating 
                                         (
                                          PostRatingID 
                                         ,PID
                                        ,UID 
                                        ,Date 
                                        ,Rate 
                                      )


 айди записи, айди поста/ коммента,  айди пользователя, дата и оценка. 

...
Рейтинг: 0 / 0
Проектирование френдленты и рейтингов
    #36606623
ViktorSemenov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Леша7771. Я бы в Posts добавил 2 столбца :
Аналогично для Comments.


Там немного хитрее формула, но да, текущий рейтинг, который обсчитывается раз в сутки для каждого элемента, будет хранится в таблицах Posts, Comments. Что бы можно было легко выводить тот же ТОП делая просто
Код: plaintext
1.
SELECT * FROM Posts ORDER BY Rating DESC LIMIT X


Да , такие вещи делаются асинхронно. (В наименее загруженное время)


Так и будет. Раз в сутки считаться.


Зачем вам таблица Activity ? Попытка запихнуть все что только можно ?
Кем создан пост и комментарий хранятся в соответствующих таблицах и этого достаточно .
Зачем их дублировать.


Тогда возникает вопрос - как во френдленте выводить в хронологическом порядке данные из разных таблиц? Т.е. мне надо вывести: кто из моих френдов написал какой-то пост, кто из моих френдов написал какой-то коммент и к чему, кто из моих френдов что-то оценил. Из одной таблицы это было бы легко:
Код: plaintext
1.
2.
3.
SELECT * FROM Activity
WHERE UIN IN (SELECT UID FROM MyFriends)
ORDER BY DateOf DESC

А если эти вещи не хранить в аггрегирующей таблице, то надо будет делать 3 запроса (к таблицам Posts, Comments, Ratings) и далее их еще как-то отсортировать по дате. А с пагинацией там еще тоже головной боли. Или я чего-то не понимаю?
...
Рейтинг: 0 / 0
Проектирование френдленты и рейтингов
    #36606937
Леша777
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нету в вашей предметной области такой сущности, как фридлента. Есть пост, коментарий, оценка, пользователь.
Если задача сделать получение фрилдленты быстро( с пэйджигами и сортировками), то данные нужно дублировать.
Не должна из-за этого появлятся непонятная таблица , типа вашей активити. Одна таблица - одна сущность. Представьте вашу систему еще чем- нибудь надо будет расширить : например, добавить более одного голосования или еще что-нибудь.

Я бы делал как описал выше. А для фридленты сделал бы доп таблицу :

id
,UID
,Date
,ExternalRecordID
,ExternalRecordType

Где ExternalRecordID - идентификатор внешней записи (поста, комментария, рэйтинга ...) , ExternalRecordType - тип . Соответственно завести табличку - справочник для типов активности.

Индекс по UID + Date сильно поможет делать эту выборку быстро.
И алгоритм с пэйджингом видится так :
1) получаете нужную страницу
2) сохраняете во временной таблице индекс в выборке, ExternalRecordID, ,ExternalRecordType
3) И union-ами соединяете выборки с соотв. базовой таблицей .

Да, появлятся доп сортировка, но всего лишь для страницы данных.
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Проектирование френдленты и рейтингов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]