domingo, 11 de mayo de 2014

Curso Datastax - Cassandra: Practica 2

Aplicación web: Playlist

Ejercicio 1 - Creando un Keyspace: 'playlist'

Abrimos el shell de Cassandra desde el terminal:
  astwin@astwin-H87-HD3:~$ cqlsh
Creamos el keyspace llamado playlist:
CREATE KEYSPACE playlist WITH replication = {
  'class': 'SimpleStrategy',  'replication_factor': '1' };
Como trabajamos en local, el factor de réplica 1 (una sola copia de los datos introducidos) y la estrategia de replicación simple (sin múltiples 'data centers').
Utilizamos este keyspace a partir de ahora:
USE playlist ;

Ejercicio 2 - Creando y cargando datos en la tabla de artistas

Creamos tabla de artistas ordenados por la primera letra del nombre:
CREATE TABLE artists_by_first_letter (
  first_letter text,
  artist text,
  PRIMARY KEY (first_letter, artist)
);
Nos permitirá realizar consultas a través de la primera letra del nombre del artista. 
Cargamos los datos de artistas proporcionados en el archivo 'artists.csv': primera letra y nombre de artista separados por caracter ' | ':
A|ARRESTED DEVELOPMENT
A|Abe Vigoda
...
cqlsh:playlist> COPY artists_by_first_letter(first_letter , artist ) FROM '/home/astwin/Escritorio/Cassandra/Leccion 2/scripts/artists.csv' WITH DELIMITER = '|';
3605 rows imported in 1.694 seconds.
Comprobamos que los datos se han cargado mirando unos cuantos registros:

cqlsh:playlist> SELECT * FROM artists_by_first_letter LIMIT 3;
 first_letter | artist
--------------+---------------------------------
            C |                  C.W. Stoneking
            C |                            CH2K
            C | CHARLIE HUNTER WITH LEON PARKER
La consulta no proporciona los resultados en orden alfabético por primera letra (first_letter: partition key), pero sí lo realiza por nombre (artist: clustering key).
Un ejemplo de consulta por letra:
cqlsh:playlist> SELECT * FROM artists_by_first_letter WHERE first_letter='N' LIMIT 5;

Ejercicio 3 - Correr la aplicación en Eclipse y ver los artistas

Cargamos el proyecto Maven descargado desde la página del curso de Datastax en Eclipse. Lo ejecutamos (clase principal StartJetty class). Abrimos la aplicación web (local): http://localhost:8080/playlist. Abrimos el apartado: “VISIT THE SONG DATABASE”. Clickeamos en alguna letra para obtener los artistas que comienzan por esa letra (se utiliza la consulta a la tabla que creamos anteriormente):

Si intentamos obtener las canciones por artista obtendremos un error, puesto que no tenemos creada la tabla track_by_artist:

Ejercicio 4 - Crear y cargar datos en la base de datos de canciones por artista (track_by_artist)

Creamos la tabla de canciones por artista:
CREATE TABLE track_by_artist (
  artist text,
  genre text,
  music_file text,
  track text,
  track_id uuid,
  track_length_in_seconds int,
  PRIMARY KEY (artist,track_id)
);
Cargamos datos desde fichero 'songs.csv' (contiene header y separación '|'):
track_id|genre|artist|track|track_length_in_seconds|music_file
c8bbc608-07ab-4586-9ba4-bedbd829c66c|classic pop and rock|Blue Oyster Cult|Mes Dames Sarat|246|TRFCOOU128F427AEC0
b3805f45-4db8-4362-bf3d-7864cfdaa0c1|classic pop and rock|Blue Oyster Cult|Screams|189|TRNJTPB128F427AE9F
....
cqlsh:playlist> COPY track_by_artist (track_id, genre, artist, track, track_length_in_seconds, music_file) FROM '/home/astwin/Escritorio/Cassandra/Leccion 2/scripts/songs.csv' WITH DELIMITER = '|' AND HEADER=true;
59600 rows imported in 16.323 seconds.
 Ahora comprobamos que ya podemos obtener las canciones por artista en la aplicación web (por ejemplo, miramos Camilo Sesto):

Ejercicio 5 - Implementar un comando 'select'

Si vamos a la letra P y al artista “Pagan's Mind” obtenemos una excepcion CQL:
Observamos el error:

com.datastax.driver.core.exceptions.SyntaxError: line 1:59 mismatched character '<EOF>' expecting '''
 at com.datastax.driver.core.exceptions.SyntaxError.copy(SyntaxError.java:35)
 at com.datastax.driver.core.ResultSetFuture.extractCauseFromExecutionException(ResultSetFuture.java:271)
 at com.datastax.driver.core.ResultSetFuture.getUninterruptibly(ResultSetFuture.java:187)
 at com.datastax.driver.core.Session.execute(Session.java:126)
 at com.datastax.driver.core.Session.execute(Session.java:77)
 at playlist.model.TracksDAO.listSongsByArtist(TracksDAO.java:65)
Si vamos al código Java del método listSongsByArtist, vemos que se realiza una consulta utilizando la API de Cassandra:
    String queryText = "SELECT * FROM track_by_artist WHERE artist = '" + artist + "'";
    ResultSet results = getSession().execute(queryText);
La consulta se crea de forma simple, utilizando un String, concatenando la consulta con la variable artist. En este caso, al contener la variable artist una comilla simple (Pagan's Mind), la consulta creada será errónea para CQL:
SELECT * FROM track_by_artist WHERE artist ='Pagan's Mind';
Necesitamos arreglar la consulta utilizando la API de Java con una consulta preparada (PreparedStatement object y BoundStatement object):
/* 
String queryText = "SELECT * FROM track_by_artist WHERE artist = '" + artist + "'";
ResultSet results = getSession().execute(queryText);
*/

// Preparamos consulta con string ? en los campos que obtendremos de variables 
   String queryText =  "SELECT * FROM track_by_artist WHERE artist =?";
   PreparedStatement prepared = getSession().prepare(queryText);
// Añadimos las variables  
   BoundStatement bound = prepared.bind(artist);
// Podemos realizar ya la consulta CQL
   ResultSet results = getSession().execute(bound);

Comprobamos que ya no se produce el error:


Ejercicio 6 - Realizando una petición por género

Necesitamos programa el método TracksDAO.listSongsByGenre() para añadir la funcionalidad de poder mostrar todas las canciones por género.

Primero será crear una nueva tabla en Cassandra (track_by_genre) para este tipo de consulta (de-normalización: crear nuevas tablas aunque suponga duplicar el almacenamiento de datos para poder ganar en velocidad).
cqlsh:playlist> CREATE TABLE track_by_genre (track_id UUID, genre TEXT, artist TEXT, track TEXT, track_length_in_seconds INT, music_file TEXT, PRIMARY KEY (genre,track,track_id))  ;
cqlsh:playlist> COPY track_by_genre  (track_id,genre,artist,track,track_length_in_seconds,music_file) FROM '/home/astwin/Escritorio/Cassandra/Leccion 2/scripts/songs.csv' WITH DELIMITER = '|' AND HEADER=true ;
59600 rows imported in 16.579 seconds.
Implementamos el método que se nos pide con la consulta adecuada por género (ver que la tabla nueva tiene como key primaria el genero, y no el artista):

 Comprobamos que ya obtenemos resultados en el apartado de búsqueda por genero:


Ejercicio 7 - Implementar 'introducir canción'

En el último apartado de la práctica se nos pide que introduzcamos una canción en la base de datos a través de la aplicación web y utilizando el modo de depuración de Eclipse comprobemos el proceso de añadir canción en el código de Java y completemos lo que pueda faltar.

Añadimos una canción utilizando la aplicación web (he añadido la canción Avicci - Hey Brother):
Comprobamos que se llama al método add() del objeto TracksDAO para insertar una nueva canción en la base de datos. Observamos como en este método sólo se implementan los comandos de insertar la nueva canción en las tablas artists_by_first_letter y track_by_artist, pero no lo hace en track_by_genre. Debemos completar este método. Importante recordar que en Cassandra se utiliza la filosofía de la denormalización, o implementar varias tablas para diversas consultas, aunque ello suponga  una redundancia en el almacenamiento de datos, y que esto implica tener que actualizar todas las tablas relacionadas ante la introducción de nuevos datos.

Comprobamos que se ha introducido correctamente y aparece en los tres tipos de consulta en la web:



No hay comentarios:

Publicar un comentario