online - mysql database designer
Facebook como el seguimiento de notificaciones(Diseño de BD) (6)
La tabla está siguiendo
Usuario
- userId (Integer)
- fullName (VarChar)
Notificación
- notificationId (Integer)
- creationDate (Fecha)
- notificationDetailUrl (VarChar)
- isRead (bollean)
- descripción (VarChar)
- ID de usuario (FK)
Solo estoy tratando de descubrir cómo la base de datos de Facebook está estructurada para rastrear notificaciones.
No entraré mucho en complejidad como Facebook. Si imaginamos una estructura de tabla simple para notificaciones:
notifications (id, userid, update, time);
Podemos obtener las notificaciones de amigos usando:
SELECT `userid`, `update`, `time`
FROM `notifications`
WHERE `userid` IN
(... query for getting friends...)
Sin embargo, ¿cuál debería ser la estructura de la tabla para verificar qué notificaciones se han leído y cuáles no?
No sé si esta es la mejor manera de hacerlo, pero como no tengo ideas de nadie más, esto es lo que haría. Espero que esta respuesta pueda ayudar a otros también.
Tenemos 2 tablas
notification
-----------------
id (pk)
userid
notification_type (for complexity like notifications for pictures, videos, apps etc.)
notification
time
notificationsRead
--------------------
id (pk) (i dont think this field is required, anyways)
lasttime_read
userid
La idea es seleccionar notificaciones de la tabla de notificaciones y unirme a la tabla de notificaciones y verificar la última notificación de lectura y las filas con ID> notificationID. Y cada vez que se abre la página de notificaciones, actualice la fila de la tabla de notificaciones de lectura.
La consulta de notificaciones no leídas supongo que sería así ...
SELECT `userid`, `notification`, `time` from `notifications` `notificationsRead`
WHERE
`notifications`.`userid` IN ( ... query to get a list of friends ...)
AND
(`notifications`.`time` > (
SELECT `notificationsRead`.`lasttime_read` FROM `notificationsRead`
WHERE `notificationsRead`.`userid` = ...$userid...
))
La consulta anterior no está marcada. Gracias a la idea del diseño db de @espais
Podría agregar otra tabla ...
tblUserNotificationStatus
-------------------------
- id (pk)
- notification_id
- user_id
- read_status (boolean)
Si desea mantener un historial, puede conservar las últimas notificaciones de X y eliminar el resto que sea anterior a su última notificación en la lista ...
Si, cuando das notificaciones, das todas las notificaciones relevantes disponibles en ese momento, puedes simplificar esto adjuntando marcas de tiempo a eventos de notificación obligatoria y haciendo un seguimiento de cuándo cada usuario recibió notificaciones por última vez. Sin embargo, si se encuentra en un entorno de servidores múltiples, debe tener cuidado con la sincronización. Tenga en cuenta que este enfoque no requiere sellos de fecha y hora verdaderos, solo algo que aumenta monótonamente.
También estoy tratando de descubrir cómo diseñar un sistema de notificación. En cuanto al estado de la notificación (leído, no leído, eliminado, archivado, etc.), creo que sería un buen candidato para ENUM . Creo que es posible que existan más de dos tipos diferentes de estado que no sean LEÍDO y NO LEÍDO, como eliminado, archivado, visto, descartado, ect.
Eso te permitirá expandirte a medida que tus necesidades evolucionen.
También creo que puede tener sentido (al menos en mi caso) tener un campo para almacenar una url de acción o un enlace. Algunas notificaciones pueden requerir o solicitar al usuario que siga un enlace.
También puede tener sentido tener un tipo de notificación si desea diferentes tipos. Estoy pensando que podría haber notificaciones del sistema (como una notificación de verificación de correo electrónico) y notificaciones solicitadas por el usuario (como una solicitud de amistad).
Aquí está la estructura, creo que sería un mínimo para tener un sistema de notificación decente.
users
-------------
id
username
password
email
notifications
-------------
id
user_id (fk)
notification_type (enum)
notification_status (enum)
notification_action (link)
notification_text
date_created (timestamp)
Veo que nadie aborda el hecho de que las notificaciones suelen volver a ocurrir, alias. la notificación de una transacción próxima siempre será la misma, pero con una identificación de transacción o fecha diferente en ella. así: {Tiene un nuevo pago próximo: @paymentID, con una fecha de vencimiento de @dueDate}. Tener textos en una mesa diferente también puede ayudar con
- Si desea cambiar el texto de notificación más adelante
- Hacer que la aplicación sea multilingüe es más fácil, porque puedo simplemente superponer la tabla de notificaciones con un código de idioma y recuperar la cadena apropiada
Por lo tanto, también hice una tabla para esas notificaciones abstractas, que solo están vinculadas bajo el usuario con una tabla intermedia, donde se puede enviar un tipo de notificación a un usuario varias veces. También vinculé las notificaciones al usuario no con una ID de clave externa, pero hice códigos de notificación para todas las notificaciones y full_text indexó el campo varchar de esos códigos, para velocidades de lectura más rápidas. Debido al hecho de que estas notificaciones deben enviarse en momentos específicos, también es más fácil para el desarrollador escribir
NotificationService::sendNew( Notification::NOTE_NEW_PAYMENT, [''paymentId''] => 123, [''dueDate''] => Carbon::now(), ''userIdToSendTo'' );
Ahora que mis mensajes van a tener datos personalizados en ellos, que se insertan en la cadena, como puede ver en el segundo argumento de antemano, los almacenaré en un blob de base de datos. como tal
$values = base64_encode(serialize($valuesInTextArray));
Esto es porque quiero desacoplar las notificaciones de otras tablas y, como tal, no quiero crear relaciones FK sin escalas desde y hacia la tabla de notificaciones, para poder decir, por ejemplo, que la notificación 234 está asociada a la transacción 23 y luego unirme y obtener ID de transacción. Desacoplando esto quita la sobrecarga de la gestión de estas relaciones. La desventaja es que es casi imposible eliminar notificaciones cuando, por ejemplo, se borra una transacción, pero en mi caso de uso decidí que esto no era necesario de todos modos.
Voy a recuperar y completar los textos en el lado de la aplicación de la siguiente manera. PD. Estoy usando la función de alguien vksprintf ( https://github.com/washingtonpost/datawrapper/blob/master/lib/utils/vksprintf.php ), apoyos para él!
$valuesToFillInString = unserialize(base64_decode($notification->values));
vksprintf( $notificationText->text, $valuesToFillInString )
Observe también qué campos indico, porque los voy a buscar u ordenar
Mi diseño de base de datos es el siguiente
===========================
TABLA: Usuarios
- id (pk)
===========================
TABLE: Notificaciones
- id (pk)
- user_id (fk, indexado)
- text_id (fk - Tabla NotificationTexts)
- values (blob) [que contiene la matriz de valores, para ingresar en la cadena de texto]
- createdDateTime (DateTime)
- leer (booleano)
[ClusterIndex] => (user_id, createdDateTime)
===========================
TABLA: NotificationTexts
- id (pk)
- text_id (uniquem indexado)
- texto (varchar) [{Usted tiene un nuevo pago venidero: @paymentID, con una fecha de vencimiento de @dueDate}]
- note (varchar, nulo) [notas para desarrolladores, columna informativa]