Archive for Windows
Creando Mondrian Schemas con PSW
Anteriormente mencionamos que los Mondrian schemas son definidos como documentos XML.
Tal vez si te sientes lo suficientemente hacker te puedas desarrollar uno de estos documentos xml con algun editor de texto.
En lo personal yo prefiero el camino medio.
Existe una app para el escritorio hecha en java que puede ayudarnos a terminar estos ficheros xml de una manera mas practica y acelerada.
Esta aplicacion fue llamada en un inicio Pentaho Cube Designer…. despues esta muto a el Pentaho Schema Workbench (PSW), el cual ofrece una interface grafica que agiliza todo. Y donde lo descargo…. (cosa facil.. del sitio de comunity de pentaho)
Hechando a volar Pentaho Schema Workbench
Pentaho Schema Workbench es arrancado usando un shell script. Shell scripts para diferentes platformas son localizable directamente sobre el directorio PSW.
Sobre Windows, solo es cosa de dar un doble click al fichero workbench.bat para levantar PSW. Sobre un sisteme POSIX, bastara con que ejecutes el comandao es bajo una terminal grafica:
chmod ug+x workbench.sh && ./workbench.sh
Despues de ejecutar el script podremos ver la siguiente pantalla:
Estableciendo una Coneccion
Despues de iniciar el PSW, tendremos que establecer una coneccion hacia una base de datos. Podremos invocar dicha coneccion mediante el dialogo menu que aparece en Tools–Preferencias
El explorador JDBC
Despues de que establescamos la coneccion, podremos abrir un ventana explorador JDBC para apreciar los contenidos de la base de datos.
Creating a New Schema
Mediante el menu seleccione File–New–Schema para lanzar el editor de Eschemas (schema editor). El schema editor posee una vista de arbol de lado izquierdo, encargado de mostrar el contenido de un Eschema. En un inicio, esto se mostrara casi vacio.
En la parte superior de la barra de tareas del schema editor encontraremos varios botones. La mayoria de estos botones estan ahi para que tu puedas agregar nuevos elementos al Eschema. En adicion a la barra de tareas del schema editor, podremos usar los menus de contexto desde la vista de arbol para completar algunas tareas. Bastara un simple click derecho sobre cualquier nodo en la vista de arbol para ver brotar los menus de contexto.
Recuerda guardar tu esquema despues de haberlo creado :p
Cambiando el Modo en que editamos el Schema Mondrian
Como ya sabemos el schema es representado como un documento XML. Si deseas ver esto,…. PSW te lo permite.
Tareas basicas para Editar un Schema Mondrian
* Crear un Eschema * Crear los cubos que contendra el Esquema ** Seleccionar nuestra tabla de hechos ** Agregar la medidas que utilizaremos (measures) * Crear dimensiones (compartibles y no compartibles) **Edicion de la gerarquia predeterminada por dimension **Definir niveles de gerarquia *Asociar dimensiones con cubos
Creando un Cubo
Para crear un cubo bastara con clickear el boton Add Cube. Despues de agregar el cubo, podremos editar sus propiedades.
Los cubos Mondrian (a que buenos cubos!) poseen los siguientes atributos:
name—Especifica el nombre que sera usado en las consultas MDX referentes a este cubo. Este debera ser uncio dentro del el schema.
caption—Especifica un nombre a visualizar, el cual sera usado por la interface de usuario para representar este cubo a el usuario final.
cache—Controla datos a ser cacheados de la tabla de hechos.
enabled—Controla el hecho de que Mondrian carge o ignore el cubo.
Existe aun otro atributo que no es actualmente sopotado por PSW:
defaultMeasure—Su uso es opcional, este atributo convierte a una de las dimensiones del cubo en la dimension predeterminada (la medida por default).
Seleccionando una tabla de Hechos (Fact Table)
El nombre de la tabla es todo lo que necesitas configurar!
Pero siempre es bueno ilustrarnos un poco mas, por lo que incluyo una descripcion mas robusta de los atributos:
schema—El identificador de el esquema de base de datos que contiene la tabla de hechos. Cuando no especificamos este de manera explicita, El esquema por defaut de la coneccion de base de datos es usado.
name—El nombre de la tabla de hechos.
alias—Este es el nombre de la tabla alias que sera utilizada por esta tabla cuando se genera instrucciones SQL. Esto suele ser muy util cuando se desea debugear instrucciones SQL generadas por Mondrian.
Agregando Medidas (Measures)
Ya que hemos configurado la tabla de hechos, ahora podremos agregar algunas medidas. Para agregar algunas medidas, Primero seleccione el cubo (o su tabla de hechos) en la vista de arbol. Y agrega la medidasobre la barra de herramientas.
![]()
El order en el cual especifiquemos las medidas realmente importa y es significativo: implicitamente, la primer medida en el cubo es considerada la medida por default. En caso de que esto no nos guste mediante el atributo del cubo defaultMeasure podemos elegir una diferente de la primera:
Atributos de la Medidas (Measures):
name—Identificador que sera usado para hacer referencia a esta medida en las consultas MDX. Este debera ser unico dentro del cubo.
aggregator—El nombre de la funcion de agregacion que es usada para la medida. El grid de atributos ofrece una caja con una lista drop-down desde la cual tu puedes seleccionar uno de estas funciones de agregacion sum, count, min, max, avg, y distinct-count. Para las medidas de ingreso y cantidad.
column—El nombre de una columna del tabla de hechos que conforma el cubo.
formatString—Este atributo define el formato con el que sera desplagada la medida
visible—Una bandera que especifica si la medida es desplegada a el usuario final en la interface de usuario.
datatype—Aqui podremos usar una lista drop-down para escoger String, Numeric, Integer, Boolean, Date, Time, o Timestamp. Cuando se retornen datos, El tipo de dato especificado (el data type) sera usado para el retorno de datos en el resultado MDX.
formatter—Podemos usar este atributo para especificar algun formateado de celda personalizado que utilice la interface mondrian.olap.CellFormatter.
caption—Especifica el nombre con el que se visualizara la medida en la interface del usuario. Si dejas este espacio en blanco, el nombre de la media es presentado en su lugar.
Agregando Dimensiones
Los Esquemas Mondrian pueden contener dimensiones en dos lugares:
Dentro del que cubo al que pertenece la dimension—Esas dimensiones son llamadas dimensiones privadas, ya que ellas son solo conocidas por el cubo que las contiene.
Dentro del esquema Mondiran mismo—Estas dimensiones son catalogadas como dimensiones compartidas y pueden ser asociadas con multiples cubos (!wow), y/o multiples veces con el mismo cubo. Las dimensiones compartidas son excelentes para implementar dimensiones que juegen roles.
Generalmente, Recomiendo que siempre uses dimensiones compartidas mas que dimensiones privadas. Ya que el proceso de creacion de dimensinoes privadas y compartidas es muy similar, la habilidad de reusar dimensiones nos proveera un considerable beneficio.
Para crear una dimension compartida, primero seleccione el schema. (Y para crear la dimension privada, seleccione el cubo que contendra le dimension.)
Las dimensiones cuentan con los siguientes atributos:
name — Para las dimensiones privadas, el nombre hace referencia a la dimension en consultas MDX. Para dimensiones compartidas, el nombre hace referencia a la dimension cuando estamos asociando esta con el cubo. Para las dimensiones privadas, el nombre debera ser unico entre todas las demas dimensiones usadas por el cubo. Para las dimensiones compartidas, el nombre debera ser unico en el schema.
foreignKey—Si esta es una dimension privada, este es el nombre de una columna de la tabla de hechos del cubo que hace referencia a la tabla dimension que corresponde a esa dimension.
type — Si tu dimension es de tiempo o relacionada con fechas, deberemos usar “TimeDimension”. Esto permitira que usemos funciones MDX para fecha y tiempo. Para otros casos usar “StandardDimension”.
usagePrefix—Esto aplica solo a dimensiones privadas.
caption—Esto mostrara el nombre usado para presentar esta dimension a el usuario final via la interface de usuario.
Agregando y Editando Gerarquias y Seleccion de Tablas Dimension
Cuando creamos una dimesion, una nueva gerarquia es tambien creada. Lograremos ver esto cuando expandamos el nodo dimension. En adicion a esto, una tabla nodo is automaticamente creada bajo el nodo Gerarquia.
La tabla nodo representa la tabla dimension que entregara los valores para los niveles de Gerarquia. El procedimiento para configurar la tabla es muy semejante a la seleccion de una tabla de hechos para el cubo.
Las Gerarquias soportan los siguentes atributos:
name—El nombre es usado en consultas MDX para hacer referencia a la gerarquia, este debera de ser unico dentro de la dimension. El hecho de omitir el nombre sera causal de que la gerarquia tome el mismo nombre que su dimension. En adicion a esto, esta Gerarquia sera considerada la Gerarquia por default.
caption—El proposito de este nombre es ser empleado para representar esta gerarquia a el usuario final dentro de la interface de usuario.
hasAll—Una bandera que indica si la Gerarquia posee un nivel “all” con un miembro “all” , por ejemplo, un solo miembro en la parte superior de la Gerarquia que representa todos los otros miembros. Usualmente debemos dejar este flag activado.
allMemberName—Si la bandera hasAll fue habilitada, este atributo especificara el identificador MDX que sera usado como el miembro “all”. Cuando este atributo es omitido, el miembro “all” sera “All + espacio + nombre de la gerarquia”.
allMemberCaption—Si la bandera hasAll fue habilitada, podremos usar este atributo para especificar el nombre que sera usado para representar al miembro “all” en la interface de usuario final.
allLevelName—El nombre usado para hacer referencia a el nivel “all” en consultas MDX.
defaultMember—El nombre de el miembro por default. Si este no es especificado, entonces el miembro “all” sera usado como miembro por default, si la gerarquia tiene un miembro All.
memberReaderClass—Nombre de una clase lectora personalizada miembro. Este atributo especifica la clase que implementara mondrian.rolap.MemberReader. Este atributo se reserva para el uso de usuarios avanzados.
primaryKeyTable—Puede ser usado para especificar el nombre de la tabla de la cual esta gerarquia consulta sus miembros. Si este atributo no es especificado, los miembros son consultados de la tabla de gerarquias. “La flexibilidad de especificar un nombre de tabla es requerida cuando se tiene que lidiar con schemas y dimensiones estilo copo de nieve.
primaryKey—Por lo general, deberiamos usar este atributo para especificar el nombre de la columna llave primaria de esta tabla dimension de la gerarquia. Para ser escatos: Este es el nombre de columna de la tabla dimensional que es referida por las filas en la tabla de hechos. Esto deberia ser una columna en esta tabla dimension de la gerarquia.
Agregando niveles a las Gerarquias
En cuando creas gerarquias, deberas definirles niveles. Podemos agregar niveles a una gerarquia existente seleccionando esta y posteriormente dando click sobre el boton “Add Level” en la barra de herramientas. Despues de añadir un nivel, se pueden editar sus atributos los cuales son los siguientes:
name—El nombre que es usado para referirce a este nivel en consultas MDX.
table—El nombre de la tabla que contiene las columnas donde la dimension de datos es almacenada para este nivel. Cuando la tabla no es especificada, la tabla de la dimension de la jerarquia sera usada. Esta suele ser el deber ser para los esquemas de estrella. Necesitaremos una tabla particular solo cuando lidiemos con esquemas copo de nieve.
column—El nombre de la columna que representa el miembro identificador para este nivel. Este debera corresponder a esta tabla de nivel.
nameColumn — El nombre de columna que contiene el nombre de este nivel. Cuando no se especifica, el valor de el nombre propiedad es usado. tipicamente deberas de dejar este en blanco.
parentColumn—Esto aplica solo para los tipos de jerarquias especiales padre-hijo. Normalmente tu dejaras esto en blanco pero si tu estas enfrentandote con jerarquias padre-hijo, utiliza este atributo para especificar la columna que hace referencia al miembro padre.
nullParentValue—Cuando nos enfrentamos con relaciones padre-hijo, deberemos usar este atributo para especificar que el miembro padre no existe. Deja este atributo en blanco cuando no estes lidiando con jerarquias padre-hijo.
ordinalColumn—Este atributo puede ser usado para especificar cual columna define como los valores de los miembros deberan ser ordenados.
type—El tipo de dato de los valores miembro. Esto es usado para controlar si y como los valores deberan ser encomillados cuando se genera SQL de las consultas MDX.
uniqueMembers—Una bandera que indicadora si todos los miembros al mismo nivel poseen valores unicos. Esto sera siempre verdad para el primer nivel (sin contar el nivel “all”) de cualquier jerarquia.
levelType—Si dejas esto en blanco, Se asume que se trata de un nivel regular,el cual es el correcto para la mayoria de las dimensiones. Dimensiones que fueron configuradas para ser del tipo TimeDimension deberan uno de los siguientes tipos de nivel: TimeYears, TimeQuarters, TimeMonths, TimeWeeks, y TimeDays. Para TimeDimensions, especificar el levelType es un prerrequisito para el correcto uso de las funciones de tiempo y datos de Mondrian, funciones tales como YTD.
hideMemberIf—Este atributo determina en que casos un miembro debera ser ocultado. Por lo general, tu puedes dejar este atributo en blanco, el cual es lo equivalente a establecer el valor a “Never”.
approxRowCount—El estimado numero de miembros a este nivel. Especificar aqui una buena estimacion puede permitir a Mondrian tomar mejores desiciones en base a como consultar y/o cachear los datos, lo cual mejora considerablemente el rendimiento.
caption—El nombre que sera usado para representar es nivel al usuario final en la interface de usuario. Cuando este no es especificado el nombre del nivel es el que sera usado.
captionColumn—Aqui podemos especificar cual columna de la tabla de dimension de nivel debera ser usada para presentar los miembros al usuario final. Cuando esto no se especifica, el miembro identificador sera usado.
formatter—Esto puede ser usado para especificar un formateador personalizado.
Asociando Cubos con dimensiones compartidas
En los esquemas Mondrian, la asociacion entre un cubo y una dimension compartida es llamada “uso de dimension”. Para agregar un uso de dimension. Para usar cualquier dimension compartida, seleccionemos el cubo y pulsemos el boton Add Dimension usage de la barra de herramientas. Entonces podremos editar los siguiente atributos para una dimension de uso:
name—El nombre que sera usado para hacer referencia a la dimension en consultas MDX. Este nombre no necesita ser identico a el nombre de la dimension compartida, mas que eso, deberemos proporcional un nombre (o un alias si tu lo haces) que refleja el especifico proposito de la dimension en relacion al cubo. La capacidad de proveer un especifico/unico nombre cada vez que se use una dimension compartida es un caso efectivo de implementacion de dimensiones jugando roles.
foreignKey—El nombre de la comlumna en la tabla de hechos del cubo que hace referencia a la llave primaria de la tabla dimension.
source—Este es el nombre de la dimension compartida.
level—Aqui tu puedes especificar un nombre de nivel de una dimension compartida que sera unido contra la tabla de hechos del cubo. Para esquemas de estrella , esto por lo regular se quedara en blanco.
caption—El nombre usado para representar la dimension a el usuario final en la interface de usuario.
Probar y Deployar
Una vez que finalices un schema. Deberas de publicar este al Pentaho BI Server antes de que tu puedas usar este para construir aplicaciones OLAP applications. Pero antes de que tu deployees este, procura hacer algunas pruebas preliminares primero.
Les dejo un minitutorial en video… para que se ilustren aun mas… antes de entrar en calor con algun caso real.
Minitutorial express en video
Planificacion de tareas al Estilo CRON en Java mediante Quartz
Crear un sistema robusto y completo que de soporte a la ejecucion de esas tareas, además de no ser una tarea facil, seria como reinventar la rueda pues ya disponemos de frameworks maduros de libre uso como el que vamos a presentar en este tutorial.
Quartz es un framework open source, con licencia Apache 2.0 para la planificación y gestión de tareas.
Planificando una de tarea
Socket Servidor multiclientes
Hola a todos tiempo de no escribir….
Ultimamente he estado bastante ocupado liberando algunos sistemas a produccion…. (cosas tediosas pero importantes)
Bueno, aqui les dejo como generar un servidor tcp/ip que reciba tramas de texto mediante Sockets de multiples clientes, este lo he desarrollado en java…
Y como lo probe?…. utilizando netcat (nc ahora)
La parte servidor basicamente esta compuesta de dos partes….. una Clase que contendra nuestro metodo Main
Y la clase que implementara todo aquello que haremos con las tramas de texto recibidas…
Fichero con funcion Main
package com.agnux.tcp;
import java.io.IOException;
import java.net.ServerSocket;
public class Main {
/**
* @param args
*/
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(6666);
} catch (IOException e) {
System.err.println("Could not listen on port: 6666.");
System.exit(-1);
}
while (listening) { new MultiClientServer(serverSocket.accept()).start(); }
serverSocket.close();
}
}
Fichero que implementa la razon de ser de nuestro Servidor Socket multiclientes
package com.agnux.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class MultiClientServer extends Thread {
private Socket socket = null;
public MultiClientServer(Socket socket) {
super("MultiClientServer");
this.socket = socket;
}
public void run() {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
out.close();
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Primera Prueba
Esto lo hice desde mi macbook…. ya se lo que estan pensando… maquina de putos… si la verdad prefiero una pc con linux… pero ya que… este comando lo corri desde la terminal de mi snowlepard
nc -v -w 2 192.168.1.181 6666 < /etc/services
Finalmente podremos ver como se despliega el flujo de texto… en la consola de la maquina donde tengas corriendo este Servidor Socket Multiclientes
Aqui les dejo algo de informacion sobre netcat http://oreilly.com/pub/h/1058
Los que usamos Mysql ya no somos tan hippies…. ?
Ahora resulta que soy experto en la base de datos open source de sun.. ?
Jamas pense que algo asi pudiece pasar con mysql….. a lo mejor tu si lo pensaste(con un porrito en mano..)….
Buscar usando LIKE o Full Text Search - php/mysql
Vamos a crear un buscador que busque en una tabla de nuestra base de datos y que según el número de palabras buscadas utilice LIKE o el Full Text Search de MySQL.
Que és Full Text Search?
El Full Text Search utiliza los índices de la tabla para hacer las búsquedas y hace las comparaciones de la misma forma que se hacen en los grandes buscadores y no como una comparación sencilla y costosa en tiempo como la utilizada por el like.
El resultado que devuelve es ordenado por similitud a las palabras o cadena buscada, esto se puede hacer ya que cuando va encontrando los resultados el mismo le asigna un indice de similitud a lo buscado, con lo que podemos saber lo exacto que es el resultado.
Para crear el índice en la tabla a buscar haremos:
ALTER TABLE noticias ADD FULLTEXT(titulo, texto);
Suponiendo que la tabla se llama noticias y los campos que queremos buscar són titulo y texto. Debemos tener en cuenta que los campos del índice solo pueden ser Char, Varchar o TEXT.
Nota: Los índices hacen que las tablas ocupen más espacio en disco peró agilizan mucho las búsquedas.
MATCH … AGAINST
Para buscar en la tabla utilizando el índice, haremos:
SELECT * FROM el índice WHERE MATCH(titulo, texto)
AGAINST ('palabras_a_buscar')
Si queremos saber noticias de similitud del resultado podemos hacer:
SELECT * FROM noticias WHERE MATCH(titulo, texto)
AGAINST ('palabras_a_buscar') AS similitud
Donde similitud sera el valor de aproximación a la busqueda.
Problemas del MATCH … AGAINST
El problema principal es que ens busquedas de una sola palabra acostumbra a fallar, ya que tiene un límite dado por el MySQL de busqueda de palabras mayores o iguales a 4 carácteres, por lo que si buscasemos por ejemplo PHP no tendriamos resultado. Lo que haremos es mirar si la cadena que nos llega es de una sola palabra o de más de una, en caso de ser una haremos la búsqueda usando LIKE y si es más de una usaremos MATCH … AGAINST Buscador con paginación.
//Conectar con la base de datos,
//también podemos poner el ADODB
//Yo utilizo conexiones con código directamente aquí
include ("conexion_bd.php");
if ($p_busca!='')
{ if (!$num) $num=0;
//Separamos las palabras usando cada espacio como separador
//Hacemos la separación de la cadena a buscar
$cadena_buscada=explode(" ",$p_busca);
if (count($cadena_buscada)==1)
{
//Si solo hay una palabra usamos LIKE
$sql=" SELECT SQL_CALC_FOUND_ROWS titulo, texto
FROM noticiasLIKE '%".$p_busca."%' OR texto LIKE '%".$p_busca."%'
WHERE titulo
LIMIT ".$num.",10";
}
elseif (count($cadena_buscada)>1)
{
//Si hay más de una palabra usaremos MATCH AGAINST
$sql=" SELECT SQL_CALC_FOUND_ROWS titulo, texto, MATCH (titulo, texto)
AGAINST MATCH (titulo,AS Score FROM noticias
('".$p_busca."') texto) AGAINST ('".$p_busca."')
WHERE BY Score DESC LIMIT ".$num.",10";
ORDER
}
$rs = $db->Execute($sql);
if (!$rs) echo $conn->ErrorMsg();
else if ($rs->fields["id"])
{ while (!$rs->EOF)
{ echo $rs->fields["titulo"].'‘.$rs->fields[”texto”];
} $rs->MoveNext();
}
else
echo ‘No se han encontrado resultados correspondientes a su búsqueda.’;
//Paginación
$rs_cont=$db->Execute (”select found_rows() as total_filas”);
if ($rs_cont->fields[”total_filas”]>10)
{ for ($i=0; $i<$rs_cont->fields[”total_filas”] && $i<50; $i=$i+10)
{ $a++;
echo '[’.$a.’] ’;
} }
}
10 cosas que linux hace bien que windows no
Mis favoritas:
>> Actualizaciones frecuentes y sin dolor todo el tiempo, Yo tengo un escritorio 3d(compiz) y una barra de busqueda(deskbar) por mas de un año sin problemas.
>> Multiple escritorios. facil, uno es muy poco para ser util.
checa la lista completa.
Microsoft permite “actualizar” a XP
Pues si que vista ya es el nuevo WindowsME 2.0, la nota aca.
Lo siento, windows vista forma parte integral del sistema
Y la estupidez(o inteligencia?) de los vendedores de productos microsoft cada vez es mayor, este es el que chigados del dia.

