ventajas update tutorial relacionales relacional modelar into for example español ejemplos dummies drop desventajas datos create column caracteristicas bases database cassandra data-modeling cqlsh

database - update - Modelo de datos de Cassandra para una aplicación de mensajería simple



update cassandra (2)

Estoy tratando de aprender a Cassandra y siempre encuentro que la mejor manera es comenzar por crear una aplicación muy simple y pequeña. Por lo tanto, estoy creando una aplicación de mensajería básica que usará a Cassandra como back-end. Me gustaría hacer lo siguiente:

  • El usuario creará una cuenta con un nombre de usuario, correo electrónico y contraseña. El correo electrónico y la contraseña se pueden cambiar en cualquier momento.
  • El usuario puede agregar otro usuario como su contacto. El usuario agregaría un contacto buscando su nombre de usuario o correo electrónico. No es necesario que los contactos tengan un significado mutuo. Si agrego un usuario, son mi contacto, no necesito esperar a que acepten / aprueben nada como Facebook.
  • Se envía un mensaje de un usuario a otro usuario. El remitente debe poder ver los mensajes que enviaron (ordenados por tiempo) y los mensajes que se les enviaron (ordenados por tiempo). Cuando un usuario abre la aplicación, necesito revisar la base de datos en busca de nuevos mensajes para ese usuario. También necesito marcar si el mensaje ha sido leído.

Como vengo del mundo de las bases de datos relacionales, mi base de datos relacional se vería así:

UsersTable username (text) email (text) password (text) time_created (timestamp) last_loggedIn (timestamp) ------------------------------------------------ ContactsTable user_i_added (text) user_added_me (text) ------------------------------------------------ MessagesTable from_user (text) to_user (text) msg_body (text) metadata (text) has_been_read (boolean) message_sent_time (timestamp)

Al leer un par de libros de texto de Cassandra, tengo una idea de cómo modelar la base de datos. Mi principal preocupación es modelar la base de datos de una manera muy eficiente. Por lo tanto, estoy tratando de evitar cosas como los índices secundarios, etc. Este es mi modelo hasta ahora:

CREATE TABLE users_by_username ( username text PRIMARY KEY, email text, password text timeCreated timestamp last_loggedin timestamp ) CREATE TABLE users_by_email ( email text PRIMARY KEY, username text, password text timeCreated timestamp last_loggedin timestamp )

Para difundir los datos de manera uniforme y para leer una cantidad mínima de particiones (con suerte solo una) puedo buscar un usuario en función de su nombre de usuario o correo electrónico rápidamente. La desventaja de esto es que obviamente estoy duplicando mis datos, pero el costo de almacenamiento es bastante bajo, por lo que me parece una buena compensación en lugar de usar índices secundarios. La última vez que inicie sesión también deberá escribirse dos veces, pero Cassandra es eficiente en las escrituras, así que creo que esta también es una buena compensación.

Para los contactos no puedo pensar en ninguna otra forma de modelar esto, así que lo modelé de manera muy similar a como lo haría en una base de datos relacional. ¿Este es un diseño bastante normalizado que creo que debería ser bueno para el rendimiento de acuerdo con los libros que he leído?

CREATE TABLE "user_follows" ( follower_username text, followed_username text, timeCreated timestamp, PRIMARY KEY ("follower_username", "followed_username") ); CREATE TABLE "user_followedBy" ( followed_username text, follower_username text, timeCreated timestamp, PRIMARY KEY ("followed_username", "follower_username") );

Estoy atascado en cómo crear esta siguiente parte. Para la mensajería estaba pensando en esta tabla, ya que creaba filas anchas que permiten ordenar los mensajes. Necesito mensajes para responder a dos preguntas. Primero debe poder mostrar al usuario todos los mensajes que tiene y también poder mostrarle los mensajes nuevos y no leídos. Este es un modelo básico, pero ¿no estoy seguro de cómo hacerlo más eficiente?

CREATE TABLE messages ( message_id uuid, from_user text, to_user text, body text, hasRead boolean, timeCreated timeuuid, PRIMARY KEY ((to_user), timeCreated ) ) WITH CLUSTERING ORDER BY (timeCreated ASC);

También estaba considerando usar cosas como columnas ESTÁTICAS para "pegar" al usuario y los mensajes, así como a SETS para almacenar relaciones de contacto, pero desde mi entendimiento estrecho hasta ahora, la forma en que presenté es más eficiente. Pregunto si hay ideas para mejorar la eficiencia de este modelo, si hay mejores prácticas para hacer las cosas que estoy tratando de hacer o si hay algún problema oculto que pueda enfrentar con este diseño.

En conclusión, estoy tratando de modelar alrededor de las consultas. Si estuviera utilizando bases de datos de relaciones, estas serían esencialmente las consultas que busco responder:

To Login: SELECT * FROM USERS WHERE (USERNAME = [MY_USERNAME] OR EMAIL = [MY_EMAIL]) AND PASSWORD = [MY_PASSWORD]; ------------------------------------------------------------------------------------------------------------------------ Update user info: UPDATE USERS (password) SET password = [NEW_PASSWORD] where username = [MY_USERNAME]; UPDATE USERS (email) SET password = [NEW_PASSWORD ] where username = [MY_USERNAME]; ------------------------------------------------------------------------------------------------------------------------ To Add contact (If by username): INSERT INTO followings(following,follower) VALUES([USERNAME_I_WANT_TO_FOLLOW],[MY_USERNAME]); ------------------------------------------------------------------------------------------------------------------------ To Add contact (If by email): SELECT username FROM users where email = [CONTACTS_EMAIL]; Then application layer sends over another query with the username: INSERT INTO followings(following,follower) VALUES([USERNAME_I_WANT_TO_FOLLOW],[MY_USERNAME]); ------------------------------------------------------------------------------------------------------------------------ To View contacts: SELECT following FROM USERS WHERE follower = [MY_USERNAME]; ------------------------------------------------------------------------------------------------------------------------ To Send Message:, INSERT INTO MESSAGES (MSG_ID, FROM, TO, MSG, IS_MSG_NEW) VALUES (uuid, [FROM_USERNAME], [TO_USERNAME], ''MY MSG'', true); ------------------------------------------------------------------------------------------------------------------------ To View All Messages (Some pagination type of technique where shows me the 10 recent messages, yet shows which ones are unread): SELECT * FROM MESSAGES WHERE TO = [MY_USERNAME] LIMIT 10; ------------------------------------------------------------------------------------------------------------------------ Once Message is read: UPDATE MESSAGES SET IS_MSG_NEW = false WHERE TO = [MY_USERNAME] AND MSG_ID = [MSG_ID];

Aclamaciones


Para los principiantes de modelado de datos de cassandra o noSQL, hay un proceso involucrado en el modelado de datos de su aplicación, como

1- Entiende tus datos, diseña un diagrama conceptual.
2- Haz una lista de todos tus deseos en detalle.
3- Haz un mapa de tus consultas usando reglas y patrones definidos, lo mejor para Cassandra
4- Crear un diseño lógico, tabla con campos derivados de consultas.
5- Ahora crea un esquema y prueba su aceptación.

Si lo modelamos bien, entonces es fácil manejar problemas como nuevas consultas complejas, sobre carga de datos, conjunto de consistencia de datos.

Después de tomar esta capacitación gratuita de modelado de datos en línea, obtendrá más claridad

https://academy.datastax.com/courses/ds220-data-modeling

¡Buena suerte!


Sí, siempre es difícil adaptarse a las limitaciones de Cassandra cuando se trata de una base de datos relacional. Como aún no tenemos el lujo de hacer uniones en Cassandra, a menudo querrás meter tanto como puedas en una sola mesa. En su caso, esa sería la tabla users_by_username.

Hay algunas características de Cassandra que deberían permitirte hacer eso.

Como usted es nuevo en Cassandra, probablemente podría usar Cassandra 3.0, que actualmente se encuentra en versión beta. En 3.0 hay una buena característica llamada vistas materializadas. Esto le permitiría tener users_by_username como tabla base, y crear users_by_email como una vista materializada. Luego, Cassandra actualizará la vista automáticamente cada vez que actualice la tabla base.

Otra característica que lo ayudará es los tipos definidos por el usuario (en C * 2.1 y posteriores). En lugar de crear tablas separadas para seguidores y mensajes, puede crear la estructura de los mismos como UDT y, a continuación, en la tabla de usuario mantener listas de esos tipos.

Entonces, una vista simplificada de su esquema podría ser así (no estoy mostrando algunos de los campos como las marcas de tiempo para mantener esto simple, pero son fáciles de agregar).

Primero crea tus UDT''s:

CREATE TYPE user_follows ( followed_username text, street text, ); CREATE TYPE msg ( from_user text, body text );

A continuación creamos tu tabla base:

CREATE TABLE users_by_username ( username text PRIMARY KEY, email text, password text, follows list<frozen<user_follows>>, followed_by list<frozen<user_follows>>, new_messages list<frozen<msg>>, old_messages list<frozen<msg>> );

Ahora creamos una vista materializada particionada por correo electrónico:

CREATE MATERIALIZED VIEW users_by_email AS SELECT username, password, follows, new_messages, old_messages FROM users_by_username WHERE email IS NOT NULL AND password IS NOT NULL AND follows IS NOT NULL AND new_messages IS NOT NULL PRIMARY KEY (email, username);

Ahora vamos a dar una vuelta y ver qué puede hacer. Vamos a crear un usuario:

INSERT INTO users_by_username (username , email , password ) VALUES ( ''someuser'', ''[email protected]'', ''somepassword'');

Deja que el usuario siga a otro usuario:

UPDATE users_by_username SET follows = [{followed_username: ''followme2'', street: ''mystreet2''}] + follows WHERE username = ''someuser'';

Enviemos un mensaje al usuario:

UPDATE users_by_username SET new_messages = [{from_user: ''auser'', body: ''hi someuser!''}] + new_messages WHERE username = ''someuser'';

Ahora veamos que hay en la tabla:

SELECT * FROM users_by_username ; username | email | followed_by | follows | new_messages | old_messages | password ----------+-------------------+-------------+---------------------------------------------------------+----------------------------------------------+--------------+-------------- someuser | [email protected] | null | [{followed_username: ''followme2'', street: ''mystreet2''}] | [{from_user: ''auser'', body: ''hi someuser!''}] | null | somepassword

Ahora comprobemos que nuestra vista materializada está funcionando:

SELECT new_messages, old_messages FROM users_by_email WHERE email=''[email protected]''; new_messages | old_messages ----------------------------------------------+-------------- [{from_user: ''auser'', body: ''hi someuser!''}] | null

Ahora vamos a leer el correo electrónico y ponerlo en los mensajes antiguos:

BEGIN BATCH DELETE new_messages[0] FROM users_by_username WHERE username=''someuser'' UPDATE users_by_username SET old_messages = [{from_user: ''auser'', body: ''hi someuser!''}] + old_messages where username = ''someuser'' APPLY BATCH; SELECT new_messages, old_messages FROM users_by_email WHERE email=''[email protected]''; new_messages | old_messages --------------+---------------------------------------------- null | [{from_user: ''auser'', body: ''hi someuser!''}]

Así que espero que te dé algunas ideas que puedas usar. Eche un vistazo a la documentación sobre colecciones (es decir, listas, mapas y conjuntos), ya que pueden ayudarlo a mantener más información en una tabla y son similares a tablas dentro de una tabla.