Comprender un sistema de notificación

15

He estado buscando cómo construir un sistema de notificación en SE y en otros lugares y me encontré atraído por la solución que es la respuesta aceptada aquí: /programming/9735578/building-a-notification-system que utiliza esta estructura:

╔═════════════╗      ╔═══════════════════╗      ╔════════════════════╗
notification       notification_object      notification_change 
╟─────────────╢      ╟───────────────────╢      ╟────────────────────╢
ID           ║—1:n—→║ID                 ║—1:n—→║ID                  
userID             notificationID           notificationObjectID
╚═════════════╝      object                   verb                
                     ╚═══════════════════╝      actor               
                                                ╚════════════════════╝

Una notificación es sobre algo (objeto = evento, amistad ...) que alguien (actor) le ha cambiado (verbo = agregado, solicitado ...) y lo ha informado al usuario (sujeto). Aquí hay una estructura de datos normalizada (aunque he usado MongoDB). Debe notificar a ciertos usuarios sobre los cambios. Entonces, son notificaciones por usuario ... lo que significa que si hubiera 100 usuarios involucrados, generaría 100 notificaciones.

Al principio pensé que entendía este enfoque, pero cuando comencé a prepararme para implementarlo, me di cuenta de que aparentemente no lo entiendo particularmente bien. Los últimos comentarios sobre la respuesta son preguntas de otros usuarios que también han tenido problemas para comprender la solución.

No estoy seguro de si este es el modelo que terminaré siguiendo, pero dada la cantidad de votos a favor que tiene, estoy seguro de que me beneficiaría entenderlo , y ciertamente me gustaría aprender más. Espero que esto también sea útil para otras personas que han tenido problemas para comprender esta solución (por cierto, no tengo suficientes puntos de Internet para dejar un comentario sobre esa respuesta que dirija a esta pregunta, ¡alguien más, por favor!)

Preguntas

Si lo entiendo bien, notifyObjectID es una clave externa que apunta a la tabla notificación_objeto , y notifyID es una clave externa que apunta a la tabla de notificación . Parece que el objeto debería ser una clave externa que se refiera a la ID de la entrada de la base de datos de la que trata la notificación (por ejemplo, un evento o publicación específica), pero ¿no necesitamos entonces otro campo para indicar a qué tabla pertenece esa ID?

El autor escribió

notify_object.object identifica el tipo de cambio, como una cadena "amistad" La referencia real al objeto cambiado con sus datos adicionales de los que hablo está en notify_change.notificationObjectID

lo cual no parece tener sentido para mí. El objeto es una cadena (¿enumeración?) Y notifyObjectID es una clave externa que se refiere al objeto del que trata la notificación? Entonces, ¿cómo están conectadas las tablas del medio y la derecha?

Parece que la tabla central especifica de qué objeto (o tipo de objeto) trata la notificación, por ejemplo, un evento o publicación. Entonces podemos tener muchas entradas en notify_change que apuntan al mismo tipo de objeto, lo que nos permite agrupar notificaciones (como "25 usuarios publicados en el muro de X), de ahí la relación 1: n entre las tablas del medio y la derecha.

Pero, ¿por qué hay una relación 1: n entre las tablas izquierda y media? ¿Vamos a dar a "25 usuarios publicados en el muro de Sam" y "Mary actualizó su evento" Viernes Picnic "con la misma ID de notificación? Si todas las notificaciones para el mismo usuario tienen la misma ID de notificación, ¿por qué necesitamos la tabla en el ¿izquierda?

Una pregunta de rendimiento: digamos que John publica un comentario sobre el evento de picnic de Mary. Parece que tendríamos que hacer una búsqueda para ver si ya existe un objeto de notificación para Mary's Picnic antes de crear la entrada de notificación de cambio . ¿Esto tendrá un impacto negativo en el rendimiento o no es un problema? Continuando con las preguntas del párrafo anterior, ¿cómo sabríamos a qué entrada de notificación dirigir el objeto de notificación ?

usuario45623
fuente

Respuestas:

8

Gracias por preguntas tan exhaustivas, y perdón por toda la confusión: comentar 1 año después de la respuesta inicial es difícil y ahora 3 años después ... los pensamientos iniciales se desvanecen y me confunden también, pero temo editar el agujero porque no estoy trabajando en el almacenamiento de notificaciones en el back-end en este momento y no estoy seguro si hago buenos juicios sin una aplicación práctica

Pienso al momento de escribir:

  • Sí y no, la Id. De notificación era una clave externa, la Id. De objeto de notificación no. Necesita otro campo FK para unir las tablas. Culpo a mi experiencia de mongo por no ser tan claro al respecto :(
  • Sí y no, notify_object.object es vago porque puede tenerlo solo como una cadena o como algo complejo (JSON o FK). En mi caso era solo un sustantivo.

Por lo tanto, todo depende de cómo se vean sus notificaciones. Para un caso simple, solo desea vincular la notificación completa a alguna URL, como la página de amigos, por eso es útil tener un objeto (entityType) como una cadena: puede vincular las URL a ella.

La notificación "tiene 3 solicitudes de amistad agregadas" se puede almacenar de manera diferente.

Si desea mostrarlos de uno en uno, tendrá 3 notificaciones, 3 objetos de notificación (friend_request) y 3 entradas en notify_change que enlazan con un usuario amigo específico.

Si desea mostrar una notificación, tendrá 1 notificación, 1 / más objetos y 3 / más acciones. Por lo tanto, en este caso complejo, como «tiene 3 solicitudes de amistad del usuario A, usuario B, usuario C», utiliza notificación de ID de objeto para cada usuario y tiene varios enlaces en el texto de notificación.

¿Deberías usar 1 o 3 objetos friend_request? Depende de

  1. Qué es el objeto y cuál es la acción. ¿Es «artículo gustado / comentado»? ¿O es "me gusta / comentario agregado" y la jerarquía de objetos se vincula solo durante la visualización? Aquí está Facebook que distingue «comentarios de fotos» de «menciones de usuarios», que semánticamente parecen estar muy cerca: tiene la misma foto, el mismo actor pero diferentes notificaciones que podrían haberse fusionado.

ingrese la descripción de la imagen aquí

  1. ¿Puedes eliminar una notificación o necesitas un historial? Entonces, si envío una solicitud de amistad y luego la cancelo, o comento y luego elimino un artículo, me gusta y luego no me gusta algo, ¿debería mostrar este historial (como otra acción) al usuario final como dos acciones diferentes? Probablemente no. Además, es técnicamente más complejo: debe buscar si hay un objeto de notificación existente, agregarle un nuevo cambio de notificación (si no es así, agregar un nuevo objeto) para que luego necesite buscar a través de cambio de notificación para eliminarlo. En su lugar, simplemente agregaría otro objeto de notificación a la misma notificación y lo eliminaría si desaparece con acciones que se eliminan en cascada.

Por otro lado, podría haber casos en los que podría ser útil tener una agrupación de acciones donde nada se borre del historial.

Creo que es por eso que al momento de escribir, se hizo una relación 1: n entre las tablas izquierda y media, para que pudiera agrupar las notificaciones no solo por actores en la misma entidad (tablas de la derecha y media) sino también por varios objetos / entidades.

Pero claro, puede simplificar todo el caso y optimizar el almacenamiento invirtiendo la relación izquierda-medio a n: 1, de modo que tenga notificaciones por usuario generadas para un evento.

Para que se vea más así ...

╔═════════════╗      ╔═══════════════════╗      ╔════════════════════╗
notification       notification_object      notification_change 
╟─────────────╢      ╟───────────────────╢      ╟────────────────────╢
ID           ║←—n:1—║ID                 ║—1:n—→║ID                  
noteObjFK          entityType               noteObjFK           
viewerUserID       entityID                 actionOnEntity      
╚═════════════╝      ╚═══════════════════╝      actorUserID         
                                                ╚════════════════════╝

Espero que esto haya ayudado

Artjom Kurapov
fuente
Genial, gracias por esta respuesta completa. Lo revisaré y le haré saber si tengo más preguntas, pero creo que esto explica las cosas muy bien.
user45623