UNIVERSIDAD CENTRAL DEL ECUADOR FACULTAD DE INGENIERÍA CIENCIAS FÍSICAS Y MATEMÁTICA CARRERA DE INGENIERÍA EN COMPUTACIÓN GRÁFICA REPRESENTACIÓN WEB DE BASE DE DATOS EN GRAFOS TRABAJO DE GRADUACIÓN PREVIO A LA OBTENCIÓN DEL TÍTULO DE INGENIERA EN COMPUTACIÓN GRÁFICA AUTOR: ALARCÓN RUIZ VIVIANA MICAELA TUTOR: ING. PEDRO ALMAGRO BLANCO QUITO – ECUADOR 2015 DEDICATORIA Dedico el presente trabajo a las personas que hicieron posible de una u otra manera que suba un escalón más en la vida. A mi familia, a mis profesores, al GMSC y amigos/as ii AGRADECIMIENTO Deseo agradecer a aquellas personas que han estado a mi lado durante toda esta etapa universitaria. A mi familia por el apoyo y la paciencia que me han brindado día a día para alcanzar una de las metas propuestas. A los profesores por compartir con nosotros todos sus conocimientos para que podamos crecer tanto en el ámbito personal como en el profesional. Al Grupo de Modelado de Sistemas Complejos que nos han guiado y entregado todo el apoyo en la culminación de nuestras carreras además de acogernos como una familia, a Pedro quien no solo ha sido mi tutor y guía académico sino también un amigo que me ha trasmitido fuerza y aliento para seguir adelante. A compañeros y compañeras con quienes hemos ido caminando juntos y mutuamente nos hemos apoyado. iii iv CERTIFICACIÓN DE TUTOR v OFICIO DE CALIFICACIÓN DEL TRABAJO DE GRADUACIÓN vi CALIFICACIÓN DEL TRABAJO DE GRADUACIÓN vii Contenido DEDICATORIA………………………………………………………………………………………………………… II AGRADECIMIENTO…………………………………………………………………………………………………. III AUTORIZACIÓN DE AUTORÍA INTELECTUAL……………………………………………………………. IV CERTIFICACIÓN DE TUTOR………………………………………………………………………………………. V OFICIO DE CALIFICACIÓN DE TRABAJO DE GRADUACIÓN ………………………………………. VI CALIFICACIÓN DEL TRABAJO DE GRADUACIÓN ……………………………………………………… VII CONTENIDO …………………………………………………………………………………………………………. VIII LISTA DE FIGURAS…………………………………………………………………………………………………… X RESUMEN……………………………………………………………………………………………………………… XII ABSTRACT……………………………………………………………………………………………………………… XIII CERTIFICADO DE TRADUCCIÓN DE RESUMEN AL IDIOMA INGLÉS………………………… XIV TÍTULO DE IDIOMA INGLES…………………………………………………………………………………… XV INTRODUCCIÓN……………………………………………………………………..….……………………………….. 1 1 CAPÍTULO I ......................................................................................................................... 3 1.1 PLANTEAMIENTO DEL PROBLEMA ...................................................................... 3 1.2 OBJETIVOS .................................................................................................................. 4 Objetivo general ..................................................................................................... 4 Objetivos específicos ............................................................................................. 4 1.3 2 JUSTIFICACIÓN .......................................................................................................... 5 CAPÍTULO II ........................................................................................................................ 7 2.1 ANTECEDENTES ........................................................................................................ 7 2.2 MARCO TEÓRICO ..................................................................................................... 11 Bases de Datos ..................................................................................................... 11 Grafos e Hipergrafos ............................................................................................ 13 Bases de Datos en Grafo ...................................................................................... 16 Neo4j .................................................................................................................... 18 Cypher .................................................................................................................. 20 HTML .................................................................................................................. 21 JavaScript ............................................................................................................. 22 CSS ...................................................................................................................... 23 JQuery .................................................................................................................. 25 D3.JS .................................................................................................................... 26 3 CAPÍTULO III ..................................................................................................................... 28 3.1 METODOLOGÍA ........................................................................................................ 28 3.2 DISEÑO DE LA APLICACIÓN WEB ....................................................................... 28 viii Librerías para grafos ............................................................................................ 28 Uso de Cypher...................................................................................................... 31 Apertura De Nodos .............................................................................................. 35 Cierre De Nodos................................................................................................... 36 Facetado Global ................................................................................................... 39 Facetado Local ..................................................................................................... 41 3.3 DISEÑO VISUAL DE LA APLICACIÓN WEB ........................................................ 45 3.4 MANUAL DE USUARIO ........................................................................................... 51 Requerimientos Del Sistema ................................................................................ 51 Uso del Navegador ............................................................................................... 51 Apertura de nodos ................................................................................................ 54 Cierre de nodos .................................................................................................... 56 Información completa del nodo ........................................................................... 56 Configuración del navegador ............................................................................... 57 4 CAPÍTULO IV..................................................................................................................... 58 4.1 CONCLUSIONES ....................................................................................................... 58 4.2 RECOMENDACIONES .............................................................................................. 60 4.3 BIBLIOGRAFÍA ......................................................................................................... 61 4.4 ANEXOS ..................................................................................................................... 63 Anexo A. Index.html ............................................................................................................ 63 Anexo B. Datos.js................................................................................................................. 68 Anexo C. Config.js ............................................................................................................... 69 Anexo D. Nodos.js ............................................................................................................... 72 Anexo E. TiposNodos.js ...................................................................................................... 77 Anexo F. TiposRelaciones.js ............................................................................................... 79 Anexo G. Funciones.js ......................................................................................................... 80 Anexo H. Información.js ...................................................................................................... 86 Anexo I. primerNodo.js ...................................................................................................... 88 Anexo J. Numvecinos.js ...................................................................................................... 91 Anexo K. PedirVecinos.js .................................................................................................... 93 Anexo L. abrirVecinos.js ..................................................................................................... 94 Anexo M. Cierre.js ............................................................................................................ 96 Anexo N. Cerrar.js ................................................................................................................ 97 ix Anexo O. funcionesBotones.js ............................................................................................. 99 Anexo P. facetadoLocal.js ................................................................................................. 103 Anexo Q. VecinosMenore.js .............................................................................................. 106 Anexo R. tipoRelaLocales.js .............................................................................................. 108 Anexo S. relacionesLocales.js ........................................................................................... 110 Anexo T. VecinoLocales.js ................................................................................................ 115 LISTA DE FIGURAS Figura 1 Linkurious ............................................................................................................ 7 Figura 2 Navegador Gephi ................................................................................................. 8 Figura 3 Navegador Mohiomap ......................................................................................... 8 Figura 4 KeyLines .............................................................................................................. 9 Figura 5 Navegador SylvaDB ............................................................................................ 9 Figura 6 Modelo Relacional ............................................................................................. 11 Figura 7 Consultas SQL ................................................................................................... 12 Figura 8 Grafo no dirigido Figura 9 Grafo dirigido ...................................................... 14 Figura 10 Camino de un Grafo......................................................................................... 14 Figura 11 Hiperaristas ...................................................................................................... 15 Figura 12 Hiper-Aristas.................................................................................................... 16 Figura 13 Base de datos en Grafos ................................................................................... 16 Figura 15 Interfaz Neo4j en LocalHost ............................................................................ 19 Figura 16 Estructura CSS ................................................................................................. 24 Figura 17 Ejemplo de D3.js con Nodos en Movimiento .................................................. 29 Figura 18 Ejemplo de D3.js con Zoom a los Nodos ........................................................ 29 Figura 19 Ejemplo de D3.js con Datos Geográficos Con Zoom ..................................... 30 Figura 20 Ejemplo de D3.js de Nodos Con Apertura y Cierre de Nodos ........................ 30 Figura 22 Ejemplo Nodos Estáticos ................................................................................. 31 Figura 23 Ejemplo utilizando Layout .............................................................................. 31 Figura 24 Consulta de 20 Nodos ...................................................................................... 32 Figura 25 Consulta de un Nodo, sus Vecinos y sus Relaciones ...................................... 33 Figura 26 Consulta de Nodos de acuerdo al Tipo de Nodo ............................................. 33 Figura 27 Nodo antes de dar click.................................................................................... 36 Figura 28 Apertura de Nodos con el evento click ............................................................ 36 Figura 29 Nodos con sus Vecinos .................................................................................... 38 Figura 30 Cierre de nodos con el evento doble click ....................................................... 38 Figura 31 Nodo con sus Vecinos ..................................................................................... 39 x Figura 32 Nodo con otros vecinos sin los anteriores ....................................................... 39 Figura 33 Tipos de Nodos ................................................................................................ 40 Figura 34 Tipos de Relaciones ......................................................................................... 40 Figura 35 Facetado Local - Tipos de Nodos Vecinos ...................................................... 42 Figura 36 Tipos de Relaciones del Nodo del Tipo seleccionado .................................... 42 Figura 37 Grupo de nodos que se relacionan con el tipo de nodo seleccionado .............. 43 Figura 38 Selección de Grupo de nodos .......................................................................... 43 Figura 39 Vecinos al azar ................................................................................................. 44 Figura 40 Nodos Guías - Tipos de Nodos ........................................................................ 45 Figura 41 Tipo de Nodo en evento mouseover ................................................................ 46 Figura 42 Opciones para el Primer Nodo ......................................................................... 46 Figura 43 Primer Nodo de la Navegación ........................................................................ 47 Figura 44 Ventana Modal - Información del Nodo .......................................................... 48 Figura 45 Collapse - Tipos de Nodos ............................................................................... 49 Figura 46 Collapse - Tipos de Relaciones........................................................................ 49 Figura 47 Facetado Local - Popover ................................................................................ 50 Figura 48 Tooltip - Nodo inicio ....................................................................................... 50 Figura 49 Tooltip - Facetado Global ................................................................................ 50 Figura 50 Criterios para Nodo inicial............................................................................... 51 Figura 51 Ejemplos de nodos que se pueden buscar ........................................................ 52 Figura 52 Nodo inicial ..................................................................................................... 52 Figura 53 Selección Tipo de Nodos ................................................................................. 53 Figura 54 Selección Tipo de Relaciones .......................................................................... 53 Figura 55 Nodos Guías .................................................................................................... 53 Figura 56 Información y Tipos de Nodos ........................................................................ 54 Figura 57 Tipos de Nodos Vecinos .................................................................................. 54 Figura 58 Tipos de Relaciones de Nodo Vecino .............................................................. 55 Figura 59 Grupo de Nodos que están conectados con nodos Vecinos ............................. 55 Figura 60 Apertura de Nodos Vecinos ............................................................................. 56 Figura 61 Cierre de Nodos ............................................................................................... 56 Figura 62 Ventana Modal con Información del Nodo ..................................................... 57 xi RESUMEN REPRESENTACIÓN WEB DE BASE DE DATOS EN GRAFOS Se presenta un prototipo de navegador web para Bases de Datos en Grafo que permite una correcta navegación a través de información altamente relacionada y con contenido multimedia, para ello se han implementado funcionalidades de navegación como son: apertura de nodos, cierre de nodos, visualización de la información multimedia y filtrado de nodos y relaciones. Para la creación del prototipo se desarrollan librerías JavaScript construidas sobre tecnologías robustas y ampliamente aceptadas en el ámbito del desarrollo web y el modelado de datos en forma de red como son: D3.js, JQuery, Cypher, Neo4j, y por supuesto HTML. DESCRIPTORES: BASE DE DATOS EN GRAFO / GESTOR DE BASES DE DATOS NEO4J / CYPHER/ PROGRAMACIÓN JAVASCRIPT / LENGUAJE HTML / LIBRERÍA D3.JS / NAVEGADOR MULTIMEDIA xii ABSTRACT Web representation of graphs databases It presents a prototype of web browser to Graph Databases in allowing a correct navigation through highly related information and multimedia content, for this has been implemented navigation features like as: opening nodes, closing nodes, visualization multimedia information and filtering nodes and relationships. For prototyping JavaScript libraries built on robust technologies are developed and widely accepted in the field of development and modeling data in a network like as: D3.js, JQuery, Cypher, Neo4j, and off course HTML. DESCRIPTORS: GRAPH DATABASE / NEO4J DATABASE MANAGER / CYPHER / JAVASCRIPT PROGRAMMING / HTML LANGUAGE/ D3.JS LIBRARIES/ MULTIMEDIA NAVIGATION xiii xiv xv INTRODUCCIÓN Las Bases de Datos en Grafo nos ofrecen nuevas formas de almacenar y tratar la información y si bien es cierto que son relativamente nuevas nos ayudan a solucionar problemas importantes en el ámbito del tratamiento de datos [4] [5]. Un caso concreto de aplicación de las Bases de Datos en Grafo es aquél en el que la información se encuentra altamente relacionada, es aquí que mediante una Base de Datos en Grafo se pueden obtener mejoras en cuanto al almacenamiento, el acceso y la representación de los datos. Neo4j es un gestor de Base de Datos en Grafo cada vez más utilizado alrededor del mundo debido a los beneficios que brinda, su rapidez y facilidades para su uso, y a su eficiencia al momento de realizar consultas, además de su fácil conexión con otras tecnologías. En la web es muy importante una correcta visualización multimedia así como una interfaz sencilla e intuitiva que facilite al usuario la navegación a través de los datos. Se pueden encontrar diversos navegadores para Bases de Datos en Grafo que utilizan diferentes tecnologías y sirven para diferentes campos profesionales o personales, se están empezando a desarrollar cada vez más plataformas de este tipo pero aún no se satisfacen todas las necesidades que el usuario requiere para un correcto análisis de las redes que investiga. Debido a que no se dispone actualmente de ningún navegador web para grafos multimedia se plantea el desarrollo de un prototipo de software para una navegación web de datos almacenados en grafo (altamente relacionados) y enriquecidos mediante contenido multimedia. Para cumplir con el objetivo principal se realiza un análisis de las tecnologías presentes de uso libre y de esta manera se determina cuáles son las más óptimas para el propósito establecido: El desarrollo de librerías JS que nos permitan crear un prototipo de navegador multimedia que pueda ser conectado con cualquier base de datos en grafo (Neo4j), y cuyos parámetros sean configurables. Los mínimos parámetros que se requiere que sean configurables son: Conexión con la base de datos, máximo de nodos vecinos a mostrar y el conjunto de atributos que se desean ver del nodo. El navegador web debe implementar diferentes funcionalidades como son apertura de nodos, cierre de nodos y opciones de filtrado (global y local). Además, la navegación debe ser interactiva de tal manera que el 1 usuario se sienta cómodo en la búsqueda de la información, para ello se integran detalles visuales que facilitan el uso de la aplicación. La aplicación ha sido diseñada para que sea capaz de conectarse con cualquier Base de Datos en Grafo (Neo4j). Debido a que el Instituto Nacional de Patrimonio Cultural (INPC) está incorporando nuevas herramientas computacionales al análisis de sus bases de datos en los últimos años [6], se ha utilizado una de sus bases de datos de este instituto como caso de uso que actualmente se encuentra almacenada en su sistema Abaco1. 1 www.inpc.gob.ec/sistema-de-informacion-para-la-gestion-de-bienes-culturales-abaco 2 1 1.1 CAPÍTULO I PLANTEAMIENTO DEL PROBLEMA En una Base de Datos en Grafo la estructura está constituida por nodos y aristas, en donde los nodos representan los registros o elementos únicos almacenados con al menos una propiedad y las aristas representan las relaciones que existen entre los elementos. En este tipo de base de datos no existe un esquema fijo con el cual modelar, de esta manera es una base de datos más flexible, la cual puede seguir creciendo o disminuyendo sin problemas ni restricciones, dando mayor importancia a sus relaciones. Debido a que un grafo es un concepto abstracto que únicamente establece relaciones entre entidades de muy diversa clase, existen dificultades en la representación visual de la información que se puede almacenar en una estructura de Base de Datos en Grafos (GDB) (Sancho Caparrini, 2014). Cuando el número de nodos y/o relaciones es muy alto, no es fácil dar una representación geométrica del grafo completo que permita comprender los distintos patrones que aparecen entre las conexiones a corta y larga distancia entre los elementos de la Base de Datos. Si, además, añadimos la característica de que el contenido que se almacena en los nodos/relaciones del grafo es enriquecido (contenido multimedia que mezcla diferentes tipos de información, desde simples textos hasta videos y audio, pasando por mapas e imágenes), nos encontramos con estructuras informativas muy complejas que requieren de nuevas formas de visualización. Las Bases de Datos en Grafo están solucionando importantes problemas con el manejo de grandes cantidades de datos altamente relacionados y con contenido dinámico, que con las bases de datos relacionales resultan complejos, es por ello que en la web existen varios navegadores para Base de Datos en Grafo, pero por ser una tecnología emergente tenemos una ausencia de navegadores completos y óptimos para que el usuario encuentre toda la información requerida de manera rápida y para que además pueda observar la información multimedia. 3 Por todo lo mencionado se hace necesario el desarrollo de una aplicación web que permita la navegación sencilla y eficaz a través de una Base de Datos en Grafo con contenido multimedia. 1.2 OBJETIVOS Objetivo general 1. Generar un conjunto de soluciones de software que puedan ser aplicadas sobre casos concretos de representación de información altamente relacionadas y con un contenido altamente enriquecido (multimedia). Objetivos específicos Estos objetivos generales se subdividen en los siguientes objetivos específicos: 1. Conocer las diversas tecnologías que pueden ser de utilidad para una correcta representación de la información en la web. 2. Estudiar con profundidad las soluciones basadas en la tecnología JavaScript y en las librerías que ya hay diseñadas en este lenguaje de programación, tanto a nivel de representación gráfica como de conexión de datos. 3. Conocer las posibles soluciones, a nivel de cliente, que puedan aplicarse al contexto del problema planteado. 4. Conectar con la información presente en el sistema Abaco del Instituto Nacional de Patrimonio Cultural (INPC) para poder ser visualizada de las formas que se estimen más adecuadas según los objetivos marcados (para usuario final, para investigadores, para gestores, etc.) 4 1.3 JUSTIFICACIÓN En los últimos años ha aparecido una buena colección de bases de datos basadas en grafo para dar soluciones a diversos problemas que venían apareciendo en el mundo de las bases de datos. En las Bases de Datos en Grafo se aprovechan las relaciones complejas y dinámicas que existen en los datos por lo que las consultas en función de las relaciones son más rápidas que las consultas en función de las propiedades de los objetos. Otra ventaja representativa de las bases de datos en grafos es que la forma de almacenamiento es más similar a la manera de pensar de las personas que las bases de datos relacionales, lo cual facilita su comprensión y da más importancia a las relaciones dentro del modelo de datos Por otro lado la navegación a través de la web por el usuario debe ser interactiva y eficiente para que pueda encontrar la información requerida rápidamente, se requiere unir la representación de las relaciones entre los datos con el contenido multimedia que éstos poseen, es por ello que se propone un prototipo de navegador web para base de datos en grafos con contenido multimedia, utilizando herramientas para el desarrollo web como el lenguaje JavaScript y librerías existentes de uso libre. Si bien es cierto existen varios navegadores en la web para Base de Datos en Grafos pero éstos tienen limitaciones las cuales requieren ser corregidas para beneficio del usuario. Una de las limitaciones más significativas es no poder mostrar los vecinos de un nodo seleccionado debido a que el número de éstos es muy elevado, esto tiene evita que la red sea accesible de manera completa. Para solucionar este problema en el prototipo desarrollado, se le ofrece al usuario la posibilidad de filtrar los nodos vecinos en función de sus características en el caso de que el número de éstos supere un límite preestablecido. Dicho límite es configurable por el gestor del navegador y por defecto tiene un valor de 25 debido a que es un valor idóneo para que el usuario pueda navegar la red sin reducir el rendimiento de la aplicación. Además, la forma de obtener los nodos vecinos en el prototipo desarrollado es aleatoria, de tal manera que el usuario siempre tiene la posibilidad de recorrer la red completa. 5 Otra de las limitaciones que se encuentran en las plataformas actuales es que no permiten la visualización de contenido multimedia asociado a los datos, es por éste motivo que en la aplicación que se presenta se ha añadido un componente que permite desplegar contenido audiovisual (imágenes, videos, audios, etc.). En el Instituto Nacional de Patrimonio Cultural (INPC), el cual se tomará como un caso de uso, disponen de un aplicativo web llamado Ábaco, que permite la visualización de las fichas de registro que contienen la información sobre el patrimonio cultural ecuatoriano, estas fichas están almacenadas en una base de datos relacional que divide al patrimonio cultural en secciones: inmaterial, inmuebles, documentos, etc. Esta base de datos es muy rica en información tanto descriptiva como audiovisual, ya que contiene anexos con archivos como imágenes (jpg), videos (mp4), documentos (doc), etc., por cada ficha. Lastimosamente es un visualizador plano, que no posee interacción con el usuario, con la implementación del prototipo de navegador web utilizando Bases de Datos en Grafo se fomenta la navegación relacional junto con un facetado que ayuda al usuario a conocer sobre el patrimonio cultural de una forma interactiva, además la integración de la parte multimedia permite una excelente experiencia de navegación. 6 2 2.1 CAPÍTULO II ANTECEDENTES En la web existen diferentes páginas que ofrecen una representación de base de datos relacional y también de Base de Datos en Grafo, desarrolladas haciendo uso de diferentes tecnologías, entre las que se encuentran: Linkurious2: Herramienta accesible con licencia comercial o gratuita en comunidad libre, utiliza el gestor de base de datos Neo4j y fue desarrollada con Sigma.js3, posee características como animaciones e interacción con el usuario, tiene restricciones con el número máximo de nodos por pantalla y es utilizada principalmente para búsqueda de datos. Figura 1 Linkurious Gephi4: es una herramienta para el análisis de datos, se puede manipular estructuras, formas y colores para interpretar características de la red que no son visibles con facilidad, es utilizado como complemento a la estadística y es un software de licencia libre desarrollado en lenguaje Java. 2 linkurio.us sigmajs.org 4 gephi.github.io 3 7 Figura 2 Navegador Gephi Mohiomap:5 es una herramienta desarrollada para visualizar y navegar a través de los datos de forma gráfica que se tiene almacenados en la nube, permite realizar mapas mentales con los archivos más importantes que se tiene almacenados y categorizar, se puede tener una agenda ordenada e interactiva. Figura 3 Navegador Mohiomap KeyLines6: es una herramienta desarrollada en JavaScript para crear aplicaciones de visualización personalizada de acuerdo al área de uso, tiene licencia empresarial, la de prueba y la académica. Este software es utilizado para análisis de datos y patrones dirigidos a la inteligencia de negocios y redes sociales. 5 6 www.moh.io/mohiomap/welcome.php keylines.com 8 Figura 4 KeyLines SylvaDB7: es un sistema de gestión de bases de datos en grafo con esquema relajado. Una herramienta idónea para la organización de datos altamente relacionados y dinámicos, es flexible ya que el usuario puede crear su propio esquema, es de uso libre, contempla el desarrollo colaborativo y además tiene una interfaz amigable que permite modelar a cualquier usuario (aunque no tenga conocimientos previos de Bases de Datos). Figura 5 Navegador SylvaDB En los últimos años ha ido aumentando el desarrollo de diferentes librerías de programación y sistemas gratuitos para el diseño web utilizando HTML y JavaScript, ya que el acceso a la información y navegación a través de la misma es más común para la obtención de conocimiento, en el Ecuador el desarrollo de las mismas están en auge, y su 7 sylvadb.com 9 objetivo a corto plazo es conseguir una mejor navegación del usuario y ofrecer respuestas inmediatas a la información requerida. 10 2.2 MARCO TEÓRICO Bases de Datos Las bases de datos actualmente se encuentra en forma digital pero en coneptos generales una base de datos es un conjunto de datos almacenados sistemáticamente de acuerdo a un mismo contexto, una base de datos muy común que se observa son las bibliotecas, donde se encuentran libros o documentos que se encuentran agrupados según su área de estudio y ser encontrados con facilidad. Una base de datos relacional (RDB) es una base de datos que cumple con el modelo relacional, que es el modelo más utilizado en la actualidad para implementar bases de datos ya planificadas. En este modelo aquellos datos que sigan una estructura semejante se almacenan en una misma tabla, y se permite establecer relaciones entre tablas distintas, de forma que se establezcan interconexiones entre datos. Sus fundamentos fueron postulados en 1970 por Edgar Frank Codd, de los laboratorios IBM en San José (California), y frente a otros modelos alternativos que surgieron en esos mismos años, no tardó en consolidarse como el nuevo paradigma en los modelos de base de datos. Figura 6 Modelo Relacional Las características principales son: Una base de datos relacional se compone de varias tablas o relaciones. No pueden existir dos tablas con el mismo nombre. Cada tabla está formada por un conjunto de registros (filas y columnas). 11 La relación entre tablas relacionadas se consigue por medio del uso de claves que identifican las filas relacionadas entre ellas. Debido a que hay una estructura común que recorre toda la base de datos, suele hablarse de su esquema como la definición de la estructura de la base de datos. Para definir un esquema de una Base de Datos relacional se necesita dar: el nombre de cada tabla, el nombre de cada columna, el tipo de dato de cada columna y la tabla a la que pertenece cada columna. Para manipular la información que hay en una RDB se utiliza lo que se denominan lenguajes relacionales. Entre ellos, el más común es el lenguaje de consultas SQL (Structured Query Language), un estándar implementado por los principales motores o sistemas de gestión de bases de datos relacionales. Figura 7 Consultas SQL Sin embargo, cuando la información que se maneja soporta su importancia tanto en las relaciones como en las propias entidades que se está estructurando, las soluciones basadas en este tipo de Bases de Datos Relacionales no resultan convincentes, por una parte, el 12 esquema se aleja cada vez más del mundo real que el individuo tiene en mente y, por otra parte, hace muy costoso desde el punto de vista técnico su mantenimiento debido a la falta de flexibilidad que el modelo proporciona. Es por ello que, al menos desde un punto de vista conceptual, y cada vez más desde un punto de vista práctico, para muchos modelados de información se están haciendo uso de nuevos sistemas de gestión de bases de datos que no siguen las normas de las tablas relacionales, y que han venido a llamarse de forma genérica como Bases de Datos NoSQL (que debe interpretarse como “No solamente SQL” y no como “No al SQL”, ya que en la mayoría de los casos intenta mantener un equilibrio entre las buenas características de las RDB y las nuevas opciones que proporcionan otro tipo de sistemas de almacenamiento y gestión) (Caparrini, 2015). Grafos e Hipergrafos La teoría de grafos se remonta al año 1736 en el que el matemático Leonard Euler resolvió un problema relacionado con los puentes de la ciudad Königsberg [1]. Un grafo es un conjunto de objetos llamados vértices o nodos unidos por enlaces llamados aristas o arcos, que permiten representar relaciones binarias entre elementos de un conjunto. Habitualmente, un grafo se puede representar gráficamente como un conjunto de puntos (o figuras geométricas) unidos por líneas en el plano (o, a veces, en el espacio tridimensional). Desde un punto de vista práctico, los grafos permiten estudiar las interrelaciones existentes entre unidades que interactúan unas con otras. Por ejemplo, una red de conceptos de un dominio puede representarse y estudiarse mediante un grafo en el cual los vértices representan los diversos conceptos que se estudian y las aristas representan conexiones (las que se consideren oportunas en el dominio, por ejemplo, sinonimia, antonimia, procede de, etc.). Prácticamente cualquier problema puede representarse mediante un grafo, y su estudio trasciende a las diversas áreas de las ciencias exactas y las ciencias sociales. 13 Figura 8 Grafo no dirigido Figura 9 Grafo dirigido Dependiendo de cómo se considera la arista que une a los vértices, los grafos se pueden clasificar como dirigidos (cuando la arista parte de uno de los vértices y llega al otro, es decir, el papel que juegan ambos nodos en la relación no es el mismo), o no dirigidos (cuando la arista simplemente conecta los vértices entre sí). Normalmente, las aristas dirigidas se representan como una flecha (tal y como vemos en la figura anterior) y las no dirigidas como un segmento. Figura 10 Camino de un Grafo Un camino en un grafo es una sucesión de vértices tal que para cada uno de sus vértices existe una arista hacia el vértice sucesor [2]. 14 Además, se pueden considerar pesos en las aristas que pueden indicar algún tipo de característica de la misma (longitud, flujo de información, fuerza de la conexión, etc.). En dicho caso, diremos que el grafo es ponderado. A veces el tipo de información que se quiere conectar no simplemente relaciona los vértices de forma binaria, es decir, de dos en dos, sino que las relaciones se producen entre conjuntos mayores de vértices. Por ejemplo, si se tiene una red de turismo en la que se considera a los turistas que viajan anualmente y las zonas que visitan, en ese caso, relacionar solo que el turista v1 visitó la zona v2 puede ser insuficiente porque depende del año en que lo hizo, en este caso se introduce un tercer tipo de vértice, temporal, y la relación se da entre los tres nodos simultáneamente: el turista v1 visitó la zona v2 en el año v3. Figura 11 Hiper-Aristas En este caso, existen posibilidades más ricas de expresión, por ejemplo: los turistas v 1 y v5 viajaron en el año v3. Estas nuevas relaciones son más complejas e informativas. Por supuesto, su representación gráfica se complica y ya no basta con representarlas por medio de segmentos conectando los puntos, y se suele acudir a representaciones de superficies para ello. A este tipo de grafos con aristas más potentes se les conoce como hipergrafos, y a las aristas de este tipo hiperaristas. Debido a que las representaciones de las hiperaristas son mucho más complejas desde un punto de vista técnico (y confusas en su representación) y como demostración de la versatilidad que tienen los grafos, no es necesario acudir a los hipergrafos aunque las relaciones no sean binarias, sino que existe la posibilidad de “crear” tipos de vértices 15 intermedios, que representen esas hiperaristas (son vértices artificiales, que no pertenecen al mundo real que se pretende modelar) de manera que si v1, v2 y v3 son vértices que comparten esa hiperarista, se crea el vértice h1 y se enlaza con aristas binarias con los tres anteriores. De esa forma no se pierde la información a almacenar y se trabaja con grafos sin necesidad de desarrollar herramientas teóricas ni de representación nuevas. Figura 12 Hiper-Aristas Bases de Datos en Grafo Una Base de Datos en Grafo (GDB) es un tipo de base de datos NoSQL que usa estructuras de grafos con nodos, aristas y propiedades para representar y almacenar la información [3]. Figura 13 Base de datos en Grafos Los nodos pueden representar entidades tales como personas, partes de un texto, conceptos, o cualquier tópico, real o no, que pueda ser útil para modelar un problema. 16 Las aristas representan relaciones entre entidades, y a diferencia de las relaciones en las RDB, en las GDB mucha de la información relevante al modelo se almacena en estas aristas. Habitualmente, cuando se decide por una implementación del modelo en un GDB es porque se requiere estudiar los patrones que emergen en las conexiones e interconexiones entre nodos, propiedades y aristas, y no tanto en la información relativa a cada uno de ellos por separado. Las propiedades son unidades de información relevante para los nodos y las aristas. Por ejemplo, si un nodo representa una comedia, propiedades relevantes podrían ser: la fecha de edición, género, extensión, etc… el hecho de que algunas de estas propiedades pasen a convertirse en nodos independientes del grafo, adquieran entidad propia, depende del objetivo a cumplir y está relacionado con el cómo estructurar la información. Además, suele ser habitual disponer de una clasificación en los nodos, de manera que se pueda agruparlos según el tipo al que pertenecen (por ejemplo, personas, obras, lugares, etc.). Debido a la libertad que ofrecen los grafos como soporte conceptual de la información, una GDB puede llegar a carecer por completo de esquema, es decir, que se puede asociar con absoluta libertad nodos entre sí, añadir propiedades de manera arbitraria e individualizada y añadir el número de relaciones que se desee entre distintos nodos. Sin embargo, suele ser habitual que, haciendo uso de la clasificación por tipos de los nodos y de las relaciones semánticas habituales que hay entre ellos (y que sean relevantes para el problema en cuestión) se trabaje sobre un esquema inicial que restrinja de alguna forma qué tipos de nodos y propiedades se pueden crear y cómo se pueden relacionar entre sí. Pero debe tenerse en mente que estas restricciones no son propias del modelo GDB, sino que tienen el fin de minimizar los posibles errores y optimizar la manipulación de datos. Comparadas con las RDB, las GDB a menudo ofrecen mayor velocidad en la búsqueda de patrones y se ajustan más directamente con el mapa conceptual del problema. Además, 17 escalan de manera más natural (es decir, no son tan sensibles al tamaño total de la base de datos) y eso facilita las consultas complejas que en las RDB pueden volverse especialmente inmanejables. Además, como dependen de un esquema mucho menos estricto son mucho más apropiadas para escenarios en que los datos pueden ser muy cambiantes (quizás por desconocimiento previo de los requisitos) y hace falta realizar evoluciones en el esquema de datos de manera frecuente. En contra, debe señalarse que especialmente para aquellos casos en que una consulta, por ejemplo, requiere mover mucha información similar, las RDB son mucho más rápidas y eficientes. Una de las ventajas adicionales del uso de las GDB es que se soportan sobre una teoría matemática muy robusta y madura, por lo que muchos de los procesos necesarios para manejar la información que se ha almacenado en ellas pueden ser resueltos por resultados matemáticos demostrados (como, por ejemplo, la búsqueda de caminos mínimos entre dos nodos del grafo, las consultas, detección de comunidades, etc.). En general, se dice que un grafo es multimedia cuando en los nodos/relaciones del grafo almacenamos contenido multimedia que, podrían ser: imágenes, audio, video, etc. Neo4j Neo4j es un gestor de base datos desarrollada en Java, que almacena la información de forma relacionada formando un grafo dirigido con sus nodos y las relaciones existentes entre ellos, es decir es un gestor de base de datos orientada a grafos. Puede integrarse con múltiples lenguajes entre ellos: Java, PHP, Ruby, .Net, Python. La base de datos está embebida en un servidor Jetty. 18 Figura 14 Interfaz Neo4j en LocalHost Es distribuida en dos versiones: la community edition (open source) y la enterprise edition. La versión comunity se diferencia de la Enterprise por no disponer de: clusterización, monitorización, backups en caliente y un sistema de cache de alto rendimiento, además de soporte de sus creadores, pero puede ser usada perfectamente para desarrollo a nivel educativo o para pequeñas aplicaciones. Una de las principales ventajas que tiene Neo4j es que se pueden efectuar las consultas directamente mediante un API REST. Es el gestor de base de datos para grafos más utilizado en el mundo por miembros de la comunidad, organizaciones y empresas, que la utilizan para el desarrollo de la educación, ciencia, tecnología y desarrollo empresarial. Utiliza el lenguaje de consulta Cypher, el cual es considerado el más potente y productivo para las consultas a una base de datos en grafos, ya que es intuitivo y fácil de aprender. No solo ofrece seguridad para las bases de datos en grafos, sino que también cumple con altos estándares de calidad que cumplen las bases de datos relacionales, como por ejemplo velocidad, rendimiento y con las propiedades ACID 8 (Atomicity, Consistency, Isolation, Durability), que garantiza la eficiencia en las consultas basadas en relaciones, que es el fuerte de los gestores de bases de datos orientados a grafos. Desde su primera versión ha ido mejorando en cada una de sus actualizaciones, con pruebas continuas y rigurosas para que sea una herramienta confiable. 8 Atomicidad: ocurren todas las transacciones o ninguna, Consistencia: no rompe la integridad de la base de datos, Aislamiento: ninguna operación afecta a otra en su ejecución y Durabilidad: una vez realizada la operación no se puede deshacer. 19 En su página web oficial dispone de una gran cantidad de información, tutoriales, ejemplos y videos que facilitan su aprendizaje9. Cypher Cypher es un lenguaje de consulta declarativa para gestores de base de datos en grafos basados en SQL, permite describir los nodos o relaciones que deseamos seleccionar, actualizar o borrar de la base de datos. Utiliza código ASCII10 (American Standard Code for Information Interchange) para representar patrones, que estructuran las consultas. De tal forma que, para definir un nodo se utilizan paréntesis de esta forma: (nodo) Una vez definido el nodo se puede referir a él asignándole una etiqueta como (p) aunque se puede usar un identificador de tal forma que ayude a identificar el nodo de una forma más natural, por ejemplo se puede usar (persona) para un nodo que se refiera a un ser humano. Para encontrar las relaciones entre los nodos se utiliza un patrón que tiene esta forma: (persona)-[v:vive_en]->(ciudad) De esta forma se pide la relación viven_en, es decir qué personas viven en cada ciudad. También se puede acceder a las propiedades (property) de los nodos utilizando una sentencia de tipo: persona.nombre esta consulta devolverá la propiedad nombre del nodo persona. O la consulta v.desde para devolver una propiedad de la relación que en el ejemplo sería vive desde (una fecha) Cypher también permite hacer uso de etiquetas (LABEL) permitiendo asignar tipos a los nodos. Por ejemplo se puede crear el nodo (p:Persona) esto creará un nodo denominado p de tipo Persona. 9 neo4j.com/docs/2.2.3 Código Estándar Estadounidense para el Intercambio de Información 10 20 Finalmente haciendo uso de la sentencia MATCH y RETURN se puede recuperar nodos o relaciones almacenadas. Por ejemplo: MATCH (p:Persona) RETURN p que devolverá los nodos p de tipo Persona. Adicionalmente Cypher permite utilizar las cláusulas Distinct, Where y Order by de la misma forma que se usan en una base de datos relacional. MATCH (c:Ciudad) WHERE ciudad.nombre = "Quito" RETURN c, devolverá el nodo c de tipo Ciudad cuyo atributo nombre posea el valor Quito. HTML Es un lenguaje de marcado que utiliza etiquetas, atributos y variables para el desarrollo de páginas web cuyas siglas traducidas al español significan lenguaje de marcas de hipertexto. Una de las características más importantes de las páginas Web modernas es que son hipertexto. Esto quiere decir que las páginas no son elementos aislados, sino que están conectadas a otras mediante links (enlaces hipertexto). Estos enlaces permiten al navegante pulsar sobre un texto de una página (un link) para navegar hasta otra página. El lenguaje de marcado HTML permite desarrollar documentos Web insertando en el texto de los mismos una serie de etiquetas que controlan los diferentes aspectos de la presentación y comportamiento de sus elementos. A su vez las etiquetas pueden contener atributos y variables. Para añadir un elemento ajeno a la página, como una imagen, un video, etc. Este no se incrusta directamente en el código de la página, sino que se hace una referencia a la ubicación de dicho elemento mediante texto. De este modo, la página web contiene sólo texto mientras que recae en el navegador web (interpretador del código) la tarea de unir todos los elementos y visualizar la página final. Las etiquetas que controlan el comportamiento del documento son fragmentos de texto encerrados entre los signos < > (mayor que y menor que) (<etiqueta>). Existen diferentes 21 tipos de etiquetas, algunas definen la presentación del texto del documento, la forma en que se incluirán en el documento elementos externos y los hiperenlaces con documentos o con diferentes partes del mismo documento. Las etiquetas funcionan la mayoría de veces en parejas, un símbolo para indicar el inicio de enlace o formato, y otro para señalar el final. La marca de inicio es una letra o una palabra (por ejemplo <B>, <TITLE>). La marca de final es la misma letra o palabra precedida por la barra inclinada o "slash" (</B>, </TITLE>). Existen algunas marcas que no requieren su pareja de cierre, por ejemplo <BR> (que fuerza un salto de línea). Para escribir HTML lo único que se necesita es un editor de texto ASCII, como el Bloc de notas de Windows. Los documentos HTML deben tener la extensión html o htm, para que puedan ser visualizados en los navegadores. JavaScript Es un lenguaje de programación interpretado que nació como un lenguaje de scripting del lado del cliente, es decir, para programar ciertos comportamientos sobre las páginas web que respondían a la interacción del usuario. Con JavaScript (JS) se pueden llevar a cabo todo tipo de acciones e interacciones como validar formularios, mostrar cajas de diálogo, etc. Además, mediante JS se pueden enviar instrucciones al navegador con el propósito de cambiar la página después de que se haya descargado. A JavaScript se le denomina "del lado del cliente" porque donde se ejecuta es en el navegador (cliente web) y es éste el que soporta la carga de procesamiento. Actualmente con JS se pueden hacer muchas cosas más como implementar todo tipo de efectos, interfaces de usuario y comunicación asíncrona con el servidor por medio de AJAX (Asynchronous JavaScript And XML). El código JavaScript se debe incluir entre las etiquetas <script>...</script>. Además, para que la página sea válida, es necesario definir el atributo type de la etiqueta <script>. Técnicamente, el atributo type se corresponde con "el tipo MIME", que es un estándar para identificar los diferentes tipos de contenidos. El "tipo MIME" correcto para JavaScript es text/JavaScript. 22 Entre las características principales de JavaScript podemos citar: - Aunque al código JavaScript se puede escribir directamente en un documento HTML, o XHTML como ocurre con las hojas de estilo CSS, suele ser más útil como un archivo independiente linkeado a cada documento que necesite de los comportamientos definidos en él. De esta forma, con un solo archivo podemos lograr que varios documentos tengan el mismo comportamiento con tan solo agregar esta línea al comienzo del documento html o xhtml que nos permite vincular el archivo independiente .js (JavaScript) al documento HTML o XHTML que deseemos. <script type="text/javascript"src="URL_de_archivo.js"></script> - JavaScript es un lenguaje interpretado, no compilado, esto quiere decir que el navegador lee, entiende y ejecuta el código, la carga está del lado del cliente. - Es case sensitive, es decir sensible a mayúsculas/minúsculas: una variable llamada matriz es diferente de otra variable llamada Matriz, por ejemplo. - Si no se termina en punto y coma las líneas de código, el intérprete de JavaScript considerará un salto de línea como el final de un enunciado. - La sintaxis de los comentarios depende del número de líneas: // …éste es un comentario de una sola línea… /* …éste es un bloque de comentarios que ocupa varias líneas… */ - Los bloques de código son un conjunto de enunciados que deben interpretarse como una secuencia completa —como por ejemplo una función—. Se indican con llaves ({}). CSS Hoja de Estilo en Cascada o CSS (siglas en inglés de cascading style sheets) permite separar los contenidos de la página de su aspecto, dentro de la propia página HTML se 23 crea una zona en la que se incluye toda la información relacionada con los estilos de la página. Existen dos maneras de incluir CSS: - Incluir CSS en el mismo documento HTML.- La etiqueta <style> crea una zona especial donde se incluyen las reglas CSS que se aplican en la página. - Definir CSS en un archivo externo.- Los estilos CSS se incluyen en un archivo de tipo CSS que las páginas HTML enlazan mediante la etiqueta <link>. Un archivo de tipo CSS no es más que un archivo simple de texto cuya extensión es .css Cada página HTML puede enlazar tantos archivos CSS como sea necesario. CSS define una serie de términos que permiten describir cada una de las partes que componen los estilos CSS. Figura 15 Estructura CSS Regla.- Cada uno de los estilos que componen una hoja de estilos CSS. Cada regla está compuesta de una parte de "selectores", un símbolo de "llave de apertura" ({), otra parte denominada "declaración" y por último, un símbolo de "llave de cierre" (}). Selector: Indica el elemento o elementos HTML a los que se aplica la regla CSS. Declaración.- Especifica los estilos que se aplican a los elementos. Está compuesta por una o más propiedades CSS. Propiedad.- Es una característica que se modifica en el elemento seleccionado. Valor.- Establece el nuevo valor de la característica modificada en el elemento. 24 JQuery JQuery no es un lenguaje, sino una serie de métodos y funciones de JavaScript. JQuery es una librería que podemos usar opcionalmente. Nos podemos referir a JQuery como framework o incluso como un API de funciones modular de JS útiles en la mayoría de proyectos web, cuando un desarrollador utiliza JavaScript, generalmente tiene que preocuparse por hacer scripts compatibles con varios navegadores y para ello tiene que incorporar código para detectar el browser del usuario, JQuery implementa una serie de clases (de programación orientada a objetos) que nos permiten desarrollar sin importar con qué navegador nos está visitando el usuario. Así pues, ofrece una infraestructura con la que se tiene mayor facilidad para la creación de aplicaciones complejas del lado del cliente por ejemplo, se obtiene ayuda en la creación de interfaces de usuario, efectos dinámicos, aplicaciones que hacen uso de Ajax, etc. El constructor de JQuery se comporta de la siguiente manera, al recibir un string lo toma como una query (consulta) y devuelve un conjunto de elementos del DOM (Modelo de Objetos del Documento), que pertenecen al resultado de la consulta y en caso de no encontrar ningún elemento que cumpla con la consulta nada devuelve un conjunto vacío. Entre las características que posee JQuery se tiene la manipulación de eventos y hojas de estilos CSS, selección de elementos de la página web, crear efectos y animaciones personalizadas, hacer uso de AJAX, entre otras. Otra característica significativa de JQuery es su flexibilidad para hacer consultas a través del DOM. JQuery básicamente permite hacer 3 tipos de consultas: CSS, Xpath y Trasversales. El archivo del JQuery ocupa unos 56 KB, el servidor lo enviará al cliente la primera vez que visite una página. En las siguientes páginas el cliente ya tendrá el archivo del framework, por lo que no necesitará transferirlo y lo tomará de la caché. Con lo que la 25 carga de la página sólo se verá afectada por el peso de este framework una vez por usuario11. D3.JS Es una librería de JavaScript que permite manipular documentos Web que se basan en datos, es decir permite visualizar datos utilizando HTML, SVG y CSS, combina elementos de visualización, transformación y manipulación de DOM. Esto se puede lograr gracias a que D3.js nos permite “conectar” datos a un DOM y generar a partir de esos datos: tablas, grafos u otras formas de visualización/transformación de datos12. D3.js nos permite representar un grafo, y otras formas de visualización de manera dinámica, gracias a que es el mejor framework de JavaScript para este uso en particular, esto lo hace valiéndose de módulos y métodos propios como13: D3.layout.force.- Para ubicar y unir los nodos. Force.nodes.- Definir u obtener un arreglo de nodos del layout. Force.links – Obtener o establecer el arreglo de enlaces entre los nodos Force.charge – Definir o recuperar la fuerza de la carga. Force.linkDistance – Obtener o establecer la distancia de los enlaces entre nodos. Force.size. – Establecer u observar el tamaño del layout en términos de x, y. D3.select.- Selecciona un elemento del documento actual. D3.selectAll.- Selecciona varios o todos los elementos .del documento actual Selection.on.- Nos permite agregar o quitar eventos que escuchan interacciones. 11 jquery.com/download d3js.org/ 13 github.com/mbostock/d3/wiki/API-Reference 12 26 Selection.append.- Crea y concatena nuevos elementos. Selection.attr.- Fija o devuelve propiedades de los elementos. Selection.data.- Obtiene o establece datos de un grupo de elementos mientras computa un join relacional entre ellos. Entre otros, siendo estos los principales módulos y métodos en que se basa una representación en forma de grafo en d3.js. Grandes conjuntos de datos pueden ser unidos a objetos SVG (gráficos vectoriales escalables) utilizando funciones simples D3 para generar texto enriquecido, gráficos y diagramas. Los datos de entrada pueden estar en diversos formatos pero comúnmente se usa JSON (JavaScript Object Notation), valores separados por comas (CSV) o GeoJSON. 27 3 3.1 CAPÍTULO III METODOLOGÍA Durante el proceso de ejecución del proyecto, se pasan por diferentes fases de aprendizaje y desarrollo. Las más relevantes son las siguientes: 1. Estudio y análisis de la teoría de grafos para un entendimiento correcto de una base de datos en grafos. 2. Estudio y análisis de las diferentes tecnologías que soportan GDB y en concreto de la tecnología Neo4j y su lenguaje de consulta (Cypher). 3. Estudio y análisis de las diferentes tecnologías que permiten la representación de datos multimedia en forma de grafo en la web (librerías JavaScript, en concreto D3.js). 3.2 DISEÑO DE LA APLICACIÓN WEB Librerías para grafos Para determinar la librería más adecuada para la implementación del prototipo se requiere de un análisis de las librerías JavaScript de uso libre que permitan la representación de grafos, entre ellas están d3.js14, sigma.js15, vis.js16, alchemy.js17. Para realizar una elección correcta se visualizan y se manipulan ejemplos de cada una de las librerías para entender sus funciones: cómo se aplican, qué acciones realizan y qué beneficios tienen, también se desarrollan pequeñas aplicaciones para establecer cuando se las puede utilizar y su efectividad en el caso concreto de Bases de Datos en Grafo y finalmente se prueban sus conexiones con los diferentes lenguajes de programación y se analiza cómo interactúan. Después de un análisis minucioso se decide utilizar la librería d3.js ya que posee las características necesarias para diseñar e implementar las librerías JS necesarias para el 14 d3js.org sigmajs.org 16 visjs.org 17 graphalchemist.github.io/Alchemy 15 28 funcionamiento del prototipo. Se considera que es la más óptima y la más completa respecto a las aplicaciones e interacciones que posee, además se considera que la librería d3.js es la más adaptable a las necesidades del proyecto, incluyendo el área multimedia. Figura 16 Ejemplo de D3.js con Nodos en Movimiento Figura 17 Ejemplo de D3.js con Zoom a los Nodos 29 Figura 18 Ejemplo de D3.js con Datos Geográficos Con Zoom Figura 19 Ejemplo de D3.js de Nodos Con Apertura y Cierre de Nodos Para iniciar con el uso de la librería D3.js se realizan pruebas simples para la comprensión de la misma: Se empieza mostrando en pantalla nodos planos sin ningún tipo de movimiento con sus respectivas relaciones, almacenados en un arreglo tipo JSON, en donde por una parte están los nodos, en este caso únicamente con las propiedades de posicionamiento y por otro están los links en donde se tiene los atributos source que contiene al nodo en el que inicia la dirección de la relación y en target se coloca el nodo en el cual termina la relación, de esta manera podemos obtener la direccionalidad de las relaciones cuando sea necesario. 30 Figura 20 Ejemplo Nodos Estáticos Luego se continúa el aprendizaje de la librería utilizando más características para hacer la aplicación interactiva, para lo cual utilizamos el método d3.layout.force el cual nos permite construir una simulación física para los nodos y sus relaciones, esto quiere decir que se puede utilizar características como gravedad, fuerza o distancia entre nodos, de igual manera con datos introducidos previamente en un JSON (JavaScript Object Notation) incrementando atributos para cada nodo: nombre, tipo e incluso rutas que contienen imágenes o videos. Por supuesto a las relaciones o links además del source y el target se les puede agregar más atributos como son tipos o nombres. Figura 21 Ejemplo utilizando Layout Uso de Cypher Para poder mostrar nodos que se encuentran en una Base de Datos en Grafo necesitamos conectar nuestro prototipo de representación de grafos en la web con un lenguaje de 31 consulta, para lo que se inicia el estudio del lenguaje Cypher y el funcionamiento de Neo4j con consultas sencillas. A continuación se muestra una de las consultas más simples que se pueden realizar con Cypher, en la cual empezamos en un nodo cualquiera de la base de datos (utilizando el símbolo *) o en un nodo específico (utilizando el identificador del nodo que se sustituirá por el símbolo *). RETURN n nos devolverá los nodos seleccionados, en vista que tenemos una base de datos extensa debemos ponerle un límite de nodos que nos va a retornar. Figura 22 Consulta de 20 Nodos A partir de esta primera consulta básica se puede construir consultas un poco más completas para obtener mayor información, en este caso se utiliza el MATCH para expresar que n tiene una relación con otro nodo que identificamos mediante x sin importar la dirección de la relación y nos retorna el nodo n, sus vecinos y sus relaciones. 32 Figura 23 Consulta de un Nodo, sus Vecinos y sus Relaciones También se puede realizar consultas más complejas restringiendo los nodos que se desea obtener. En el MATCH definimos 2 relaciones, la de n con x y otra de x con b, lo que se desea obtener son los nodos x que sean de tipo Inmaterial, que estén relacionados con n y que estén relacionados con nodos que sean de tipo Ámbito, finalmente se pide que nos retorne los nodos n,x y b y sus respectivas relaciones con un límite de 20 resultados. Figura 24 Consulta de Nodos de acuerdo al Tipo de Nodo 33 Dentro del desarrollo de la aplicación se realizan 11 consultas a la base de datos similares a las que se muestran en los ejemplos anteriores, pero en este caso se debe realizar las consultas cypher con JavaScript mediante una petición AJAX(Asynchronous JavaScript And XML) asíncrona para que permita continuar con la navegación y no bloquee la aplicación , de esta manera se obtiene la información requerida directamente de la base de datos en tiempo real, esto es fundamental para que la aplicación sea capaz de conectarse con cualquier Base de Datos en Grafo. 34 Apertura De Nodos La librería D3 nos permite manejar eventos con el mouse para tener una mayor interacción con los nodos. Tabla 1 Eventos del Mouse Evento mouseover Función Pasar el puntero del mouse sobre el elemento. mouseout Retirar el puntero del mouse del elemento. click Dar clic sobre el elemento. dblclick Dar doble clic sobre el elemento. En el evento click sobre el nodo se llama a la función unclick la cual invoca a su vez a varias funciones (véase Anexo G - unclick), entre las cuales se encuentra la función para la verificación del número de nodos vecinos que posee el nodo seleccionado para proceder con la apertura de nodos. En el caso que el número de nodos vecinos sea menor o igual al límite establecido se realiza la consulta para que nos retorne todos sus vecinos, se guarda todos los datos necesarios por cada elemento, para lo que se invoca a la función abrirvecinos en la cual se verifica si el nodo que se quiere añadir no se encuentra ya almacenado, en ese caso se almacena junto con su relación como datos JSON para finalmente actualizar la visualización en pantalla (véase Anexo LAnexo K). La actualización del svg en pantalla se realiza reiniciando el force (método de D3.js para ubicación de nodos en el layout) de los nodos y redibujando con sus características los nodos y sus relaciones (véase Anexo G- ActalizaGrafo). 35 Figura 25 Nodo antes de dar click Figura 26 Apertura de Nodos con el evento click Cierre De Nodos Una vez que la apertura de nodos funciona correctamente, se debe pensar en la manera más sencilla posible para que el usuario pueda quitar nodos que no le interesa en su navegación. Debido a que en el evento click se utiliza la apertura de nodos, para el usuario es más intuitivo que para el cierre de los mismos se utilice el evento dblclick (doble click) sobre los nodos (véase Anexo G - Dosclick). Se debe analizar las diferentes posibilidades que se tiene para cerrar los nodos vecinos del nodo que ha sido seleccionado por el usuario para ser eliminado, entre las cuales se tiene: 36 1. Cerrar los nodos vecinos sin cerrar sus nodos padres ni tampoco el nodo seleccionado. 2. Cerrar el nodo y todos sus vecinos. 3. Cerrar todos sus vecinos y dejar el nodo seleccionado. Después de analizar la lógica de cada una de las formas de cerrar los nodos se decide que el cierre se realizará de manera que se elimine el nodo seleccionado y sus vecinos (opción 2), siempre y cuando no sean nodos padres (que significa que no sea el nodo del cual se origina el nodo seleccionado) o tengan relacionados más de un nodo, en el caso que sus nodos vecinos tengan más de una relación pero no sean padres se eliminará únicamente la relación con el nodo seleccionado. Para realizar la eliminación de nodos lo primero que se hace es guardar el nodo seleccionado dentro de un arreglo en el que se guardarán todos los nodos a eliminarse (Véase Anexo M). A continuación se busca todos los nodos vecinos que tenga el nodo seleccionado verificando todas las relaciones, una vez que tengamos todos sus vecinos se verifica el número de relaciones que tiene cada nodo vecino, si el nodo tiene una sola relación que corresponda a la que lo une con el nodo seleccionado se agrega al arreglo de nodos a ser eliminados y en el caso que tenga más de una relación o se encuentre almacenado en una posición anterior al nodo pulsado, no serán eliminados. Finalmente se compara los nodos que se tiene almacenados en el arreglo de eliminados con los nodos que se encuentran en nodes (arreglo donde se encuentran almacenados todos los nodos que se están visualizando), y se elimina uno por uno si coincide, de la misma manera se maneja las relaciones tomando en cuenta que primero se debe eliminar las relaciones que tengan los nodos para luego eliminar los nodos (véase Anexo N). 37 Figura 27 Nodos con sus Vecinos Figura 28 Cierre de nodos con el evento doble click Una vez finalizada la implementación del cierre de nodos y al verificar el funcionamiento general, se observa que si se vuelve a dar click sobre un nodo que ya tenga sus vecinos visibles se muestran más vecinos permaneciendo también los anteriores, lo que puede hacer que aumente de manera drástica el número de nodos en pantalla, por esta razón se decide que en este caso se eliminen primero los nodos que estén visibles para de esta forma mostrar los nuevos vecinos del nodo seleccionado (de esta forma, además se le da la posibilidad a el usuario de que recorra la Base de Datos completa). Para implementar la solución se coloca un condicional para verificar la acción, si se da doble click para eliminar todos los nodos o si se da click, en el último caso antes de abrir 38 los nodos vecinos se verifica si ya tiene vecinos el nodo pulsado y de ser así primero se elimina los nodos vecinos que no tengan más relaciones y luego se muestra otros vecinos. (Véase Anexo N). Figura 29 Nodo con sus Vecinos Figura 30 Nodo con otros vecinos sin los anteriores Facetado Global Ya con la estructura de navegación básica funcionando correctamente, se necesita una manera simple y rápida para que el usuario tenga la posibilidad de filtrar los nodos y las relaciones. Al observar las bases de datos en grafos y su estructura, se tiene a los nodos y a sus relaciones agrupados por tipos, haciendo uso de esto, se obtendrá los diferentes tipos de 39 nodos y tipos de relaciones que tenga la base de datos para mostrarlos en pantalla y darle al usuario la opción de elegir los tipos que le interesa observar durante su navegación, tomando en cuenta que puede variar su elección en cualquier momento. Para la obtención de los tipos de nodos y relaciones se realiza una consulta mediante el lenguaje de consulta Cypher a la base de datos, una vez que se devuelven todos los tipos se almacenan y se agregan junto a un checkbox (véase Anexo E Anexo F). Luego en funciones separadas se verifica si cada checkbox de tipo de nodo o tipo de relación está seleccionado para según esto construir las consultas de manera tal que sólo se obtengan nodos y relaciones de los tipos seleccionados (véase Anexo G – tipNodos y tipRelaciones). Figura 31 Tipos de Nodos Figura 32 Tipos de Relaciones 40 Facetado Local Al momento de abrir los nodos vecinos a un nodo dado en una Base de Datos en Grafo con datos reales nos encontramos usualmente con un número extremadamente grande, por lo cual es imperativo que se tenga una manera de restringir este comportamiento mostrando únicamente un número limitado de vecinos, para que el usuario pueda tener mayor facilidad a la hora de captar la información y pueda navegar sin complicaciones. Cuando se da click sobre un nodo, primero se realiza una consulta a la base de datos para determinar cuántos nodos vecinos tiene el nodo pulsado, de acuerdo a esto se realiza la siguiente llamada a otra función con una consulta diferente, en el caso que el número de nodos vecinos sea mayor al límite establecido se deben filtrar de alguna manera para mostrar los nodos que al usuario más le interese (véase Anexo J). Ya que en una base de datos en grafos es más eficiente realizar consultas según las relaciones que por sus propiedades, se va a realizar un filtrado por el tipo de nodos vecinos y por el tipo de relaciones que posean sus vecinos, para ello primero consultamos qué tipos de nodos tiene como vecinos y cuantos son de cada tipo, se los almacena para luego mostrarlos en una lista para que el usuario pueda seleccionar un tipo determinado (véase Anexo P). Si el número de nodos vecinos del tipo seleccionado es menor o igual al límite establecido nodos aparecen automáticamente los vecinos (véase Anexo Q), pero si el número de nodos es mayor se realiza otro filtro en donde se muestra una lista con el tipo de relaciones que tienen los nodos vecinos del nodo seleccionado y de igual manera se selecciona una de las opciones que se presente (véase Anexo R). De acuerdo a lo seleccionado se realiza una nueva consulta con los filtros correspondientes, en esta nueva consulta lo que se obtiene son los nodos que están conectados con este tipo de relación y el número de nodos vecinos que tienen la relación escogida y están conectados con el nodo que se muestra, en esta parte del filtrado se presenta la lista junto a checkbox para que el usuario pueda escoger uno o varios grupos de nodos (véase Anexo S). 41 Para tener más claro este paso se va a ejemplificar. Si un nodo de tipo provincia tiene nodos vecinos de tipo cantón e inmaterial y se desea ver los vecinos de tipo inmaterial. Figura 33 Facetado Local - Tipos de Nodos Vecinos Al escoger se despliega la lista de tipos de relaciones que tienen los nodos de tipo inmaterial, por ejemplo nos despliega que tiene relaciones de tipo comunidad, lengua, ámbito, subámbito, detalle de subámbito, cantón, parroquia, etc. Figura 34 Tipos de Relaciones del Nodo del Tipo seleccionado Si se elige en este caso por ejemplo ámbito nos desplegará las opciones de nodos relacionados que tiene. Por ejemplo, nodos de tipo inmaterial cuyo ámbito es tradiciones y expresiones orales o aquellos cuyo ámbito es artes del espectáculo... 42 Figura 35 Grupo de nodos que se relacionan con el tipo de nodo seleccionado Si en este caso se escoge únicamente artes del espectáculo que tiene 151 nodos lo que se va a obtener son 25 (límite establecido) nodos vecinos de tipo inmaterial relacionados con el nodo artes del espectáculo. En el caso de elegir más de un grupo de nodos se procede de la siguiente manera: se divide el límite que se tiene para los nodos, que en este caso es 25, para el número de checkbox que se encuentren seleccionados para tener un límite provisional para cada consulta que se realizará por cada selección que se hizo. Figura 36 Selección de Grupo de nodos Debido a que Neo4j retorna los nodos en forma ordenada desde el primer nodo encontrado, para poder visualizar diferentes nodos en cada consulta y abarcar mayor extensión al 43 navegar en la base de datos se utiliza skip en la consulta Cypher la cual indica cuántas posiciones saltar antes de seleccionar los nodos e ingresaremos un valor aleatorio de acuerdo al número de nodos (esto nos permite retornar en cada caso un conjunto diferente de vecinos). De tal manera que la consulta (en el caso descrito) se realiza con los parámetros anteriormente escogidos que son: el tipo de nodo vecino, el tipo de nodo que tiene relacionado el vecino, el nombre del nodo con el tipo escogido, el punto de inicio que se obtendrán los nodos y el límite de nodos que se obtiene por cada consulta. Figura 37 Vecinos al azar 44 3.3 DISEÑO VISUAL DE LA APLICACIÓN WEB El desarrollo visual se realiza una vez que las funcionalidades de la aplicación han sido implementadas, ordenando cada elemento de la navegación: el facetado global, el facetado local, guías, información de los nodos e inicio desde un nodo determinado. De esta manera el usuario podrá tener una visualización amigable y de fácil entendimiento. Se ha escogido la librería de estilo CSS Bootstrap18 ya que se considera que es la librería que posee los componentes adecuados para la presentación de este proyecto. Los nodos se grafican de diferentes colores de acuerdo al tipo al que pertenezca, para que el usuario pueda identificar de qué tipo son los nodos que se encuentran en pantalla se coloca en la parte superior nodos guías con los respectivos colores y al momento de pasar el mouse sobre los nodos guías nos muestra el nombre del tipo al que corresponde, de la misma manera si se pone el mouse sobre los nodos se podrá observar a qué tipo de nodo corresponde. Para poder mostrar las etiquetas de la manera descrita se utiliza la librería d3-tip19, que es una librería adjunta a la librería d3.js. Figura 38 Nodos Guías - Tipos de Nodos 18 19 getbootstrap.com github.com/Caged/d3-tip 45 Figura 39 Tipo de Nodo en evento mouseover La aplicación inicia sin ningún nodo en pantalla para dar la opción al usuario de escoger desde qué nodo desea iniciar su navegación, para ello se coloca un textbox o cuadro de texto junto con un botón y un desplegable utilizando la librería de bootstrap (específicamente input groups – buttons with dropdowns) en donde se podrá escoger el criterio de selección del nodo inicial. Las opciones que se presentan son Provincia, Cantón y Lengua. Figura 40 Opciones para el Primer Nodo Se debe seleccionar primero el criterio mediante el que se desea buscar, luego ingresar el nombre y luego hacer click en buscar, entonces se mostrará en pantalla el primer nodo para comenzar con la navegación. 46 Figura 41 Primer Nodo de la Navegación Con el evento mouseover se visualiza el nombre del nodo, como se observa en la figura anterior, el nodo es de tipo Provincia y su nombre es Pichincha, para observar la información completa del nodo se tiene que dar click sobre el nombre y se despliega una ventana modal con características de la librería de estilo Bootstrap. La ventana modal consta de un título el cual corresponde al nombre del nodo seguido de la información o atributos que posee el nodo, debajo de la información se encuentra el contenido multimedia como pueden ser imágenes, videos, documentos o audios y finalmente un botón para cerrar o también se puede cerrar dando click fuera de la ventana modal. La información se la muestra utilizando la función infoNodos (véase Anexo H), se realiza una comparación entre los datos que se encuentran almacenados en el nodo y los datos que se desea mostrar, los cuales fueron previamente definidos en el archivo de configuración, se toma dato por dato el nombre del atributo y su valor para ir agregando a la ventana modal de forma ordenada. Para la información multimedia se toma la información almacenada en el nodo seleccionado, se verifica el tipo de archivo y se lo muestra dentro del modal. 47 Figura 42 Ventana Modal - Información del Nodo Se tiene un archivo de configuración en el cual se define el enlace donde se encuentra la base de datos, el número máximo de nodos a mostrar, y un diccionario para definir los atributos del nodo que se desea mostrar dentro de la ventana modal. El diccionario se lo realiza utilizando hashtable, que es una variable tipo objeto en la cual se almacena el nombre del dato y su valor, como si fuera una matriz (véase Anexo C). Para la presentación del facetado o filtrado global se utiliza el elemento de la librería bootstrap collapse – collapse group20 el cual nos permite mostrar únicamente los títulos que en este caso sería Tipos de Nodos y Tipos de Relaciones, se puede observar la información que contiene dando click sobre el nombre, al momento que se requiere abrir la siguiente pestaña la anterior se contrae, dentro se tiene los tipos de nodos y relaciones con los respectivos checkbox para la selección. 20 getbootstrap.com/javascript/#collapse-example-accordion 48 Figura 43 Collapse - Tipos de Nodos Figura 44 Collapse - Tipos de Relaciones La visualización del facetado local se realiza dentro de un popover el cual contendrá los select con los tipos de nodos vecinos, tipos de relaciones y los nodos. 49 Figura 45 Facetado Local - Popover El usuario necesita guías para conocer sobre la utilización de los elemento de la aplicación web, se coloca tooltip con la librería Bootstrap en los diferentes elementos indicando cuál es su función. Figura 46 Tooltip - Nodo inicio Figura 47 Tooltip - Facetado Global 50 3.4 MANUAL DE USUARIO El presente prototipo de un navegador web de una base de datos en grafos permite navegar a través de sus elementos online, en este caso los bienes culturales del INPC, observando todas las relaciones que existen entre los datos, además de representar la información multimedia. La navegación a través de grafos proporciona una visualización de los datos en su contexto lo que ayuda al usuario a tener un mayor entendimiento sobre el tema que se encuentra investigando. Requerimientos Del Sistema Debido a que es un navegador web, para la utilización de la aplicación se necesita el navegador web de su elección. Uso del Navegador La aplicación consta de varias partes esenciales: - Input group: el cual consta de un cuadro de texto, un botón y un dropdown. Este elemento se utiliza para seleccionar el nodo desde el que se iniciará la navegación. Figura 48 Criterios para Nodo inicial Se debe seleccionar un criterio para la selección del nodo inicial: Provincia, Cantón o Lengua (Los criterios pueden variar de acuerdo a la base de datos a la cual esté conectada la aplicación). Si sabe el nombre del nodo con el cual desea empezar se escoge una de estas opciones y se escribe en el cuadro de texto el nombre y se procede a dar click en buscar. 51 En el caso de no saber el nombre del nodo por el que se desea empezar tenemos la opción de ID Nodo con el que se puede ingresar un número que corresponde al identificador o posición del nodo dentro de la base de datos. Figura 49 Ejemplos de nodos que se pueden buscar Una vez ingresado el dato se debe dar click en el botón buscar y se mostrará el primer nodo. Figura 50 Nodo inicial - Facetado global: esta parte es importante para restringir la navegación en el caso de no desear ver todos los tipos de nodos o todos los tipos de relaciones. Para ajustar este comportamiento se debe dar click sobre el nombre tipos de nodos o en tipos de relaciones para que se despliegue la información y seleccionar o deseleccionar los tipos que se deseen, por defecto viene todos los tipos marcados, esto quiere decir que se podrá observar los nodos de todos los tipos que posee la base de datos. 52 Figura 51 Selección Tipo de Nodos Figura 52 Selección Tipo de Relaciones - Nodos guías: los nodos guías son los que se encuentran justo debajo del facetado global, los cuales ayudarán a el usuario a entender los colores en los nodos y el tipo al que pertenecen, solo se necesita pasar el puntero del mouse sobre dichos nodos o a su vez se puede ver el nombre del tipo de los nodos al momento de pasar el puntero por cualquier nodo nos dará el nombre del tipo que le corresponde de acuerdo al color. Figura 53 Nodos Guías 53 Figura 54 Información y Tipos de Nodos Apertura de nodos Para abrir los nodos vecinos de un nodo dado, se debe dar click sobre el nodo, en el caso que el número de nodos vecinos sean menores al límite establecido se mostrarán automáticamente (el número máximo de nodos que se mostrarán en pantalla se lo puede configurar desde el archivo config.js que por defecto se encuentra en 25), en caso contrario se abrirá un popover el cual contendrá un select en donde tendremos la lista de tipos de nodos a los que pertenecen los nodos vecinos junto con el número de vecinos que tiene de cada tipo. Figura 55 Tipos de Nodos Vecinos Al escoger una de las opciones se tiene 2 posibilidades la primera es que si el número de nodos es menor al límite establecido se abra automáticamente y la segunda que si es mayor al límite establecido se abrirá un segundo select en el cual se desplegarán los tipos de relaciones que van a tener los nodos vecinos del tipo escogido. 54 Figura 56 Tipos de Relaciones de Nodo Vecino Se debe elegir un tipo de relación y se mostrarán los nodos que están relacionados con los nodos vecinos con el tipo de relación escogida junto con el número de nodos vecinos que tienen dicha relación, se puede escoger uno o varios nodos seleccionando los checkbox. Figura 57 Grupo de Nodos que están conectados con nodos Vecinos Una vez escogidos los nodos se debe dar click al botón denominado Vecinos para que se muestren los nodos vecinos. 55 Figura 58 Apertura de Nodos Vecinos Cierre de nodos Si no desea observar algunos de los nodos que se muestran en pantalla, éstos se puede ocultar haciendo doble click sobre ellos. De ésta forma, también se eliminarán los vecinos que no tengan más de una relación o que se hayan almacenado antes del nodo pulsado. Figura 59 Cierre de Nodos Información completa del nodo Si se desea conocer más información sobre un nodo en específico lo que se debe hacer es dar click sobre el nombre que aparece al pasar el puntero sobre el mismo y se abrirá una ventana modal en la que se podrá mirar toda la información sobre el nodo. Los datos que se pueden encontrar son: nombre completo del nodo, descripción del nodo, descripción de algunas relaciones con otros nodos, información multimedia que pueden 56 ser imágenes, videos, audios, o archivos de texto, descripción de la información multimedia, entre otras. Figura 60 Ventana Modal con Información del Nodo Configuración del navegador En el caso que se desee administrar el navegador para utilizarlo con una Base de Datos en Grafo (Neo4j) diferente, se deben configurar algunos parámetros en el archivo config.js. Para conectar la base de datos con la aplicación se debe cambiar la ruta de enlace que se encuentra almacenada en la variable enlace. El máximo de nodos vecinos que se obtienen de un nodo seleccionado se puede cambiar en la variable totalimite. Para establecer qué propiedad se utiliza como etiqueta de los nodos se debe configurar la variable camp_tooltip, esto se realiza de acuerdo a los tipos de nodos que tenga la base de datos, para cada tipo se debe ingresar el nombre del atributo a mostrar. En la variable camp_modal se configura los atributos que se desea visualizar de la información general asociada a un nodo, en cada tipo de nodo se crea una lista de atributos que se desee mostrar. 57 4 4.1 CAPÍTULO IV CONCLUSIONES En la web se puede encontrar información y tecnologías de libre uso suficientes para desarrollar nuevas formas de representación de una Base de Datos en Grafo como la aplicación implementada en el presente proyecto, adaptándolos a las necesidades profesionales o personales que se tengan e innovando en su creación. La navegación a través de una Base de Datos en Grafo puede proporcionar mayor información que en una base de datos SQL y más cuando se tiene elementos altamente relacionados y con un contenido multimedia, que puede ser utilizado para un análisis más profundo de la red y su comportamiento. Después del análisis de las diferentes tecnologías existentes se determinó que las más adecuadas y eficientes para la elaboración de un nuevo prototipo son: Neo4j, D3.js, JQuery y Bootstrap (aparte de Javascript y HTML, tecnologías estándar para el desarrollo web). D3. Js es una librería muy robusta para la representación de información, no solo en forma de grafos, y junto a las demás tecnologías se puede obtener resultados muy favorables en diferentes campos de aplicación. Neo4j es uno de los gestores de Base de Datos en Grafo más eficientes al momento de realizar consultas basadas en las relaciones (así sean estas muy complejas), su lenguaje de consulta Cypher posee una estructura muy sencilla pero permite obtener resultados muy completos. La librerías desarrolladas permite tener funcionalidades generales como el cierre y la apertura de nodos, combinadas con configuraciones personalizadas como la información que se desea mostrar del nodo para cada tipo de área en la que pueda emplear la aplicación. En el caso de uso del INPC se puede aprovechar al máximo sobre todo en la presentación de la información multimedia por su riqueza y además el usuario puede tener una visión más completa de cómo se encuentran conectados los bienes culturales en el Ecuador. Gracias al uso correcto de las tecnologías y herramientas empleadas se pudo solucionar un problema latente en los navegadores de base de datos en grafos (incluyendo Neo4j), que es la visualización de los nodos vecinos a pesar que haya un número extremadamente grande de éstos. 58 La presentación visual de la aplicación influye sobre el usuario, ya que si no tiene una aplicación intuitiva y con directrices que le ayuden en su navegación ésta puede resultar confusa, precisamente para evitar este problema la aplicación cuenta con guías en sus elementos y tiene una interfaz intuitiva. El aprendizaje obtenido diseñando e implementando las librerías complementa el estudio teórico del diseño y programación web, permitiendo tener una visión más clara sobre qué es lo que necesita el cliente para tener una experiencia constructiva a través de la web. 59 4.2 RECOMENDACIONES Debido a que es un prototipo experimental se tiene trabajo por delante para mejorarlo y que pueda ser presentado al público. En el facetado local se puede obtener mejores resultados de filtrado si se realiza mediante las propiedades de los nodos, de esta manera se tendría un facetado global por tipos y un facetado local por propiedades, debido a que las consultas en las Bases de Datos en Grafo son más eficientes por relaciones se perdería efectividad aumentando el tiempo de respuesta y utilizando recursos innecesarios, se podría solucionar utilizando por debajo consultas por relaciones y luego por propiedades con esto tendríamos resultados más selectivos y mejoraría la captación del usuario. La aplicación unida a otras librerías de representación de información como angular.js o sigma.js se podría potencializar, obteniéndose una navegación a través de los nodos con mayor número de características y funcionalidades para mejorar la experiencia del usuario, incluso utilizando otras librerías implementadas que hacen uso de D3.js con diferentes métodos se obtendría por ejemplo la navegación actual con opciones de agrupación de nodos para un análisis selectivo de la red. La presentación de la aplicación web se puede mejorar aplicando y desarrollando librerías CSS adicionales con las cuales además de los componentes que se tiene se pueda agregar animaciones al abrir nodos, al mostrar su información o que la aplicación pueda ser utilizada en dispositivos móviles, también se puede utilizar un diseño personalizado con el uso de atributos CSS en los diferentes elementos. Se podría implementar un historial de acciones realizadas y mostrarlas en pantalla para que el usuario pueda tener un control sobre en qué parte de la navegación se encuentra, indicando paso a paso cómo ha ido navegando a través de la red: Qué nodos abrió el usuario, qué nodos cerró o incluso de qué nodos mostró su información. 60 4.3 BIBLIOGRAFÍA 1. EULER, L. (1736). "Solutio problematis ad geometriam situs pertinentis". Commentarii Academiae Scientiarum Imperialis Petropolitanae 8. 128-140. 2. LIPSCHUTZ, S; LIPSON, M. "Matemáticas Discretas". McGraw-Hill, 1976. Cap 8. 3. ROBINSON, I.; WEBBER, J y EIFREM, E (2013). Graph Databases. 4. ALMAGRO, P; ORDOÑEZ, S. “Generador de Grafos Multirrelacionales a partir de Redes Sociales”. Ingeniería, vol. 19, no. 1, pp. 8-18, Mayo 2014. ISSN 0121-750X E-ISSN 2344-8393. 5. DE LA ROSA, J; SUÁREZ, J; SANCHO, F. “Sustaining a Global Community: Art and Religion in the Network of Baroque Hispanic-American Paintings”. Leonardo Transactions, 2011. 6. ALMAGRO, P.; DÁVILA, E; GUERRERO, G; MEDINA, I.; REGALADO, E ; RUÍZ, Z; SALVADOR, J; SANCHO, F. “Nuevas líneas metodológicas aplicadas al patrimonio cultural ecuatoriano”. Revista del Patrimonio Cultural del Ecuador, Vol 6, I Semestre 2015, ISSN 1390-9231 (Directora: Elena Noboa Jiménez). 7. FERNANDO SANCHO CAPARRINI. “Estructurando y consultando información en grafos”, [Online] http://www.cs.us.es/~fsancho/?e=84 8. FERNANDO SANCHO CAPARRINI. “Base de Datos en Grafo”, [Online] http://www.cs.us.es/~fsancho/?e=79 9. Mozzila. "JAVASCRIPT REFERENCE", developer.mozilla.org. [Online] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference 10. D3.JS. "D3.JS DOCUMENTATION", Github [Online] https://github.com/mbostock/d3/wiki 11. SIGMA.JS. "SIGMA.JS DOCUMENTATION", Github [Online] https://github.com/jacomyal/sigma.js/wiki 12. JQUERY. “JQUERY API”, [Online] http://api.jquery.com/ 13. NEO4J. "NEO4J DOCUMENTATION", [Online] http://docs.neo4j.org/ 61 14. NEO4J. "CYPHER QUERY LANGUAGE", [Online] http://docs.neo4j.org/chunked/milestone/cypher-query-lang.html 15. NEO4J. "REST API", [Online] http://docs.neo4j.org/chunked/milestone/restapi.html 16. BOOTSTRAP. “BOOTSTRAP FRAMEWORK”, [Online] http://getbootstrap.com 17. D3-TIP. “D3.TIP API DOCUMETATION”, [Online] https://github.com/Caged/d3-tip/blob/master/docs/index.md 18. SYLVA. “GRAPH DATABASES SYLVA MADE EASY FOR EVERYONE”, [Online] http://sylvadb.com/ 19. LINKURIOUS. “LINKURIOUS FEATURES”, [Online] http://linkurio.us/product/ 20. INSTITUTO NACIONAL DE PATRIMONIO CULTURAL DEL ECUADOR [Online] http://inpc.gob.ec/ 62 4.4 ANEXOS Anexo A. Index.html <html> <meta charset="utf-8"> <body> <!-- librerias --> <script src="../static/js/resourse/d3.js"></script> <script type='text/javascript' src="../static/js/resourse/d3.tip.v0.6.3.js"> </script> <script src="../static/js/datos.js"></script> <!-- configuración de datos --> <script src="../static/js/config.js"></script> <!-- información del nodo para visualizar en el modal --> <script src="../static/js/informacion.js"></script> <script src="../static/js/estilos.js"></script> <!-- librerias de estilos --> <script src="../static/js/resourse/jquery-2.1.3.js"></script> <LINK rel="stylesheet" href="../static/css/resourse/bootstrap.css"> <script src="../static/js/resourse/bootstrap.js"></script> <LINK rel="stylesheet" href="../static/css/resourse/bootstrap-popoverx.css"> <script src="../static/js/resourse/bootstrap-popover-x.js"></script> <script src="../static/js/resourse/bootstrap-modalpopover.js"></script> 63 <link rel="stylesheet" href="../static/css/EstiloGrafi.css"> <script src="../static/js/cierre3.js"></script> <!-- collapse del facetado global --> <h4>FACETADO GLOBAL</h4> <div class="panel-group" id="accordion2" style="width:65%; float:left; padding-left:30px;"> <div class="panel panel-default"> <div id="titnodos" class="panel-heading"role="tab" > <a class="accordion-toggle" data-toggle="collapse" data- parent="#accordion2" href="#collapseOne"> TIPOS DE NODOS </a> </div> <div id="collapseOne" class="accordion-body collapse"> <div class="panel-body" id="mi_div"> </div> </div> </div> <div class="panel panel-default"> <div id="titRelaciones" class="panel-heading"role="tab"> <a class="accordion-toggle" data-toggle="collapse" dataparent="#accordion2" href="#collapseTwo"> 64 TIPOS DE RELACIONES </a> </div> <div id="collapseTwo" class="accordion-body collapse"> <div class="panel-body" id="mi_div2"> </div> </div> </div> </div> <!-- textbox, botón y dropdown para la busqueda inicial de nodo --> <div class="col-xs-3" > <div class="input-group" id="empezar"> <input id="Buscador" type="text" class="form-control" aria-label="..."> <div class="input-group-btn "> <!-- Button and dropdown menu --> <button class="btn btn-default" type="button" id="PrimerNodo">Buscar</button> <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false" > <span class="caret"></span> <span class="sr-only">Toggle Dropdown</span> </button> <ul class="dropdown-menu" role="menu"> 65 <li><a href="#" id="provincia" name="Provincia">Provincia</a></li> <li><a href="#" id="canton" name="Canton">Cantón</a></li> <li><a href="#" id="lengua" name="Lengua">Lengua</a></li> <li class="divider"></li> <li><a href="#" id="idnodo">ID Nodo</a></li> </ul> </div> </div> </div> <script src="../static/js/tiposRelaciones.js"></script> <script src="../static/js/TiposNodos.js"></script> <script src="../static/js/Nodos.js"></script> <script src="../static/js/funciones.js"></script> <script src="../static/js/numVecinos.js"></script> <script src="../static/js/PedirVecinos.js"></script> <script src="../static/js/funcionesBotones.js"></script> <script src="../static/js/PrimerNodo.js"></script> <!-- modal que muestra la informacion extendida de los nodos --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" arialabelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> 66 <button type="button" class="close" data-dismiss="modal" arialabel="Close"><span aria-hidden="true">&times;</span></button> <h4 class="modal-title" id="myModalLabel"></h4> </div> <div id="mi_div6" class="modal-body"> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" datadismiss="modal">Close</button> </div> </div> </div> </div> <script src="../static/js/vecinosLocal.js"></script> <script src="../static/js/abrirVecinos.js"></script> <script src="../static/js/facetadoLocal2.js"></script> <script src="../static/js/vecinosMenores.js"></script> <script src="../static/js/tipoRelaLocales.js"></script> <script src="../static/js/relacionesLocales.js"></script> <script src="../static/js/cerrarVecinos.js"></script> </body> </html> 67 Anexo B. Datos.js // arreglos en donde se guardaran los nodos y sus relaciones var nodes = []; var links = [ ]; Estilo.js var w = 1500, h = 650; //Radio de nodos var circleWidth = 10; var fontFamily = 'Bree Serif', fontSizeHighlight = '1.5em', fontSizeNormal = '1em'; // Gama de colores var palette = { "lightgray": "#819090", "gray": "#708284", "mediumgray": "#536870", "darkgray": "#475B62", "darkblue": "#0A2933", "darkerblue": "#042029", "paleryellow": "#FCF4DC", "paleyellow": "#EAE3CB", "yellow": "#A57706", 68 "orange": "#BD3613", "red": "#D11C24", "pink": "#C61C6F", "purple": "#595AB7", "blue": "#2176C7", "green": "#259286", "yellowgreen": "#738A05" } Anexo C. Config.js var enlace ="http://localhost:7474/db/data/cypher" //Máximo de nodos para mostrar var totalimite=25; //Nombres de los Nodos de acuerdo al tipo var etiqueta={}; etiqueta["Alcance"] = "det_alcance_desc"; etiqueta["Ambito"] = "amb_descripcion"; etiqueta["Canton"] = "can_descripcion"; etiqueta["Comunidad"] = "com_descripcion"; etiqueta["Detalle"] = "inmaterial_id"; etiqueta["DetalleSubambito"] = "dsa_descripcion"; etiqueta["Elemento"] = "nombre"; etiqueta["ElementosSig"] = "nombre"; etiqueta["Herramientas"] = "nombre"; etiqueta["Inmaterial"] = "inmaterial_denominacion"; 69 etiqueta["Lengua"] = "len_descripcion"; etiqueta["Parroquia"] = "par_descripcion"; etiqueta["Periodicidad"] = "det_periodicidad_desc"; etiqueta["Preparativo"] = "nombre"; etiqueta["Producto"] = "nombre"; etiqueta["Provincia"] = "pro_descripcion"; etiqueta["Sensibilidad"] = "sensibilidad_desc"; etiqueta["Subambito"] = "sua_descripcion"; etiqueta["Tecnica"] = "nombre"; etiqueta["UsoSimbolico"] = "det_uso_simbolico_desc"; //Campos que se muestran en el tooltip de los nodos var camp_tooltip ={ "Alcance":["det_alcance_desc"], "Ambito":["amb_descripcion"], "Canton":["can_descripcion"], "Comunidad":["com_descripcion"], "Detalle":["inmaterial_id"], "DetalleSubambito":["dsa_descripcion"], "Elemento":["nombre"], "ElementosSig":["nombre"], "Herramientas":["nombre"], "Inmaterial":["inmaterial_denominacion"], "Lengua":["len_descripcion"], "Parroquia":["par_descripcion"], 70 "Periodicidad":["det_periodicidad_desc"], "Preparativo":["nombre"], "Producto":["nombre"], "Provincia":["pro_descripcion"], "Sensibilidad":["sensibilidad_desc"], "Subambito":["sua_descripcion"], "Tecnica":["nombre"], "UsoSimbolico":["det_uso_simbolico_desc"], } //Campos que se muestran al abrir toda la informacion var camp_modal ={ "Alcance":["det_alcance_desc","det_alcance"], "Ambito":["amb_descripcion","amb_codigo"], "Canton":["can_descripcion","pro_codigo"], "Comunidad":["com_descripcion","com_codigo"], "Detalle":["inmaterial_id","uso_alcance_desc"], "DetalleSubambito":["dsa_descripcion","dsa_codigo"], "Elemento":["nombre","inmaterial_id"], "ElementosSig":["nombre","inmaterial_id"], "Herramientas":["nombre","inmaterial_id"], "Inmaterial":["inmaterial_denominacion","inmaterial_id","inmaterial_sen si_desc","comunidad_nombre","lengua_nombre"], "Lengua":["len_descripcion","len_codigo"], "Parroquia":["par_descripcion","pro_codigo","can_codigo","par_codigo"], "Periodicidad":["det_periodicidad_desc","det_periodicidad"], 71 "Preparativo":["nombre","inmaterial_id"], "Producto":["nombre","inmaterial_id"], "Provincia":["pro_descripcion","pro_codigo"], "Sensibilidad":["sensibilidad_desc","sensibilidad_id"], "Subambito":["sua_descripcion","sua_codigo"], "Tecnica":["nombre","inmaterial_id"], "UsoSimbolico":["det_uso_simbolico_desc","det_uso_simbolico"], } Anexo D. Nodos.js // Se crea y configura la parte visual mediante la libreria D3js los nodos y relaciones var guia; var color = d3.scale.category20(); var vis = d3.select("body") .append("svg:svg") .attr("class", "svg-tam"); var force = d3.layout.force() .nodes(nodes) .links(links) .charge(-150) .linkDistance(50) .size([w, h]); 72 // Flechas para la direccion de las relaciones vis.append("svg:defs") .selectAll("marker") .data(["end"]) .enter().append("svg:marker") .attr("id", String) .attr("viewBox", "0 -5 10 10") .attr("refX", 40) .attr("refY", -1.5) .attr("markerWidth", 6) .attr("markerHeight", 6) .attr("orient", "auto") .append("svg:path") .attr("d", "M0,-5L10,0L0,5 L10,0 L0, -5") .style("stroke", "#4679BD") .style("opacity", "0.9"); // .attr("d", "M0,-5L10,0L0,5"); //tooltip en los nodos var tip = d3.tip() .attr('class', 'd3-tip') .offset([0, 7]) .html( function(d){ var titulo=datosNodo.join(); 73 //limita la cantidad de caracteres que se muestran de la variable titulo= titulo.substring(0,10); //muestra el nombre del nodo en un boton junto con icono de informacion return "<button type='text' class='btn btn-primary btn pull-right' data-toggle='modal' data-target='#myModal' id='leermas'> <img src='../static/img/Icono_información.png' class='icono' >"+titulo+"... </button>"; } ) vis.call(tip); //tooltip para los nodos guias var tip2 = d3.tip() .attr('class', 'd3-tip2') .offset([-7, 0]) .html(function (d) { return d.label; }) vis.call(tip2); // se crea el nodo con la informacion que esta en nodes y los agrega al grupo g var node = vis.selectAll("circle.node") .data(nodes) .enter() .append("g") .attr("class", "node") .style("cursor","pointer") 74 .call(force.drag); //CIRCLE y sus atributos node.append("svg:circle") .attr("r", circleWidth) .style("cursor","pointer") .attr("fill", function(d, i) { return color(d.label); // se crea las relaciones con su estilo var link = vis.append("g").selectAll(".link") .data(links) .enter().append("line") .attr("class", "link") .style("marker-end", "url(#end)"); // se crea nodos guias con sus atributos function guias(){ guia = vis.selectAll("circle.guia") .data(tiposNodes) .enter() .append("svg:circle") .attr("r",circleWidth) .attr("id", function(d,i){return "guia"+d.label}) .attr("fill",function(d,i) {return color(d.label)}) .attr("cx", function(d,i) { return (i*30)+20}) .attr("cy", 30) .on("mouseover", guiatool) 75 } ) .on("mouseout", tip2.hide) } function guiatool(d){ tip2.show(d); } force.on("tick", function(e) { node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .attr("transform", function(d, i) { return "translate(" + d.x + "," + d.y + ")"; }); link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }) node.each(collide(0.5)); }); force.start(); var padding = 1, // separation between circles radius=6; function collide(alpha) { var quadtree = d3.geom.quadtree(nodes); return function(d) { var rb = 2*radius + padding, 76 nx1 = d.x - rb, nx2 = d.x + rb, ny1 = d.y - rb, ny2 = d.y + rb; quadtree.visit(function(quad, x1, y1, x2, y2) { if (quad.point && (quad.point !== d)) { var x = d.x - quad.point.x, y = d.y - quad.point.y, l = Math.sqrt(x * x + y * y); if (l < rb) { l = (l - rb) / l * alpha; d.x -= x *= l; d.y -= y *= l; quad.point.x += x; quad.point.y += y; } } return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; }); }; } Anexo E. TiposNodos.js //Con esta consulta se obtiene todos los tipos de nodos que contiene la base de datos y se los muestra junto a un checkbox para el facetado global var consulta2 = { "query" : "START n=node(*) RETURN distinct labels(n)", 77 "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta2), dataType: "json", contentType: "application/json", success: function( data ) { tiposNodes = []; //Se agrega cada tipo encontrado a un arreglo for(i=0; i<data.data.length; i++){ t={label:data.data[i][0][0]}; tiposNodes.push(t); } for (j = 0; j < tiposNodes.length; j++) { $( "#mi_div" ).append( "<div class='seleccionable'> <input +tiposNodes[j].label+"</div>" type='checkbox' id="+j+" checked >" ); } guias(); }, error: function( xhr ) { print('error retrieving schema'); 78 window.console && console.log( xhr ); }, complete: function(data) { } }) Anexo F. TiposRelaciones.js //Se obtiene todos los tipos de relaciones que contiene la base de datos y los muestra junto a un checkbox para el facetado global var consulta3 = { "query" : "START r=rel(*) return distinct(type(r))", "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta3), dataType: "json", contentType: "application/json", success: function( data ) { tiposRelaciones = []; for(i=0; i<data.data.length; i++){ tiposRelaciones.push(data.data[i][0]); 79 } for (i = 0; i < tiposRelaciones.length; i++) { $("#mi_div2").append("<div class='seleccionableR'><input type='checkbox' id="+i+"r checked>"+tiposRelaciones[i] +"</div>" } ); }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { } }) Anexo G. Funciones.js var tp =0; var popopen =0; //Verifica los checkbox de los tipos de nodos en el facetado global que esten en check //para agregarlos a la variable tiposN como string y realizar las consultas function tipNodos(){ tiposN=""; checkeado =[]; for(m=0; m<tiposNodes.length; m++){ var label = $('#'+m+'').is(":checked"); 80 if(label){ checkeado.push(tiposNodes[m].label); } } for(k=0; k<checkeado.length; k++){ if(k==checkeado.length-1){ tiposN = tiposN+" x: "+checkeado[k]; } else{ tiposN = tiposN+" x: "+checkeado[k]+" or"; } } } //Verifica los checkbox de los tipos de relaciones en el facetado global que esten en check //para agregarlos a la variable tiposR como string y realizar las consultas function tipRelaciones(){ tiposR=""; checkeadoRel =[]; for(p=0; p<tiposRelaciones.length; p++){ var rela = $('#'+p+'r').is(":checked"); if(rela){ checkeadoRel.push(tiposRelaciones[p]); } 81 } for(o=0; o<checkeadoRel.length; o++){ if(o==0){ tiposR = " and type(re)='"+checkeadoRel[o]+"' or "; } if(o != 0 && o != checkeadoRel.length - 1){ tiposR = tiposR+" type(re)='"+checkeadoRel[o]+"' or"; } if(o==checkeadoRel.length-1){ tipos= tiposR+" type(re)='"+checkeadoRel[o]+"'"; } } } // Detecta un click sobre el nodo para la apertura de nodos var doblclic=false; function unclick(d){ var temp = this; setTimeout(function(){ if(doblclic==false){ d3.select(temp).selectAll("circle") .transition() .duration(250) .style("cursor", "pointer") .attr("r", circleWidth*2); 82 tp++; //esconde el tooltip tip.hide(d); //llama las funciones que verifican el facetado global tipNodos(); tipRelaciones(); showPopover (); //llama a la funcion numVecinos para verificar el numero de vecinos que tiene el nodo numVecinos(d.sid); $("#mi_div3").empty(); } },200); } //función doble click cierra los nodos function dosclick(d){ doblclic=true; d3.select(this).selectAll("circle") .transition() .duration(250) .style("cursor", "pointer") cerrar(d.sid); $("g").popover('hide'); tp = 0; setTimeout(function(){ 83 doblclic=false },200); } // Actualiza la presentacion en pantalla de nodos y relaciones function actualizaGrafo(){ force.start(); node = node.data(force.nodes(), function(d) { return d.sid; }); node.enter() .append("g") .attr("class", "node") .append("circle") .attr("r", circleWidth) .style("cursor", "pointer") .attr("fill", function(d, i) { ) .on("mouseover", infoNodos) .on("mouseout", ocultarInfo) .on("click", unclick) .on("dblclick", dosclick) .call(force.drag); node.exit().remove(); $("g").popover( { 'html':'true', 84 return color(d.label); } 'title':'FACETADO LOCAL', 'content':"<div id='loader1'><img src='../static/img/loading.gif'></div><select style='display:none' id='mi_div3' ></select>"+ "<div style='display:none' id='loader2'><img src='../static/img/loader.gif'></div></br><select style='display:none' id='miselec'></select>"+ "<div style='display:none' id='loader3'><img src='../static/img/loader.gif'></div><div style='display:none' id='mi_div5'></div>"+ "</br></br><input style='display:none' type='button' id='btnSubmitL' value='Vecinos' /></br></br></br>", 'container': 'body', 'placement': 'bottom', }) link = link.data(force.links(), function(d) { return d.source.x +"-"+d.target.x; }); link.enter() .append("line") .attr("class", "link") .style("stroke", "#ccc") .style("stroke-width", function (d) { return Math.sqrt(d.value);}) .attr("marker-end", "url(#end)"); link.exit().remove(); } 85 var showPopover = function () { console.log("primer"+tp); if(tp>1){ $("g").popover('hide'); tp=0; } }; $("body").click(function(e){ if(e.target.localName == "svg" ){ $("g").popover('hide'); $("[role='tooltip']").popover('hide'); tp=0; }}); Anexo H. Información.js //función infoNodos muestra la información del tooltip function infoNodos(d){ console.log(d); $("#mi_div6").empty(); $("#myModalLabel").empty(); //Cuando se tiene mas de un campo que mostrar en el tooltip for(x=0; x < nodes.length; x++){ if(nodes[x].sid == d.sid){ datosNodo=[]; 86 for(t=0; t<camp_tooltip[d.label].length; t++){ $.map(nodes[x], function(value, key) { if(key==camp_tooltip[d.label][t]){ datosNodo.push(value); } }); }}} //muestra el tooltip tip.show(d); tip2.show(d, document.getElementById("guia"+d.label)); //Agrega el nombre del nodo al titulo de la ventana modal $( "#myModalLabel" ).append( ""+d[etiqueta[d.label]]+"" ); //Verifica los campos que tiene el nodo con los campos definidos para mostrar en el modal for(x=0; x < nodes.length; x++){ if(nodes[x].sid == d.sid){ for(w=0; w<camp_modal[d.label].length; w++){ $.map(nodes[x], function(value, key) { if(key==camp_modal[d.label][w]){ 87 $( "#mi_div6" ).append( key+ ": ", " "+value+ "</br>" ); }}); }}} //Imagen fija para mostrar en modal $( "#mi_div6" ).append( "<img src='../static/img/GENERAL.jpg' >" ); } //se oculta la información del tooltip despues de 2000 milisegundos de retirar el mouse del nodo //para que puedan dar click sobre el nombre para abrir toda la información function ocultarInfo(d){ setTimeout(function(d){ tip.hide(d); },2000); tip2.hide(d); } Anexo I. primerNodo.js // las funciones PrimerNodo y Nodo1 llaman al primer nodo que pide el usuario mediante la busqueda function PrimerNodo(nodoini){ var consulta4 = { 88 "query" : "START n=node("+nodoini+") MATCH n-[re]-x RETURN n, ID(n),count (x) ", "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta4), dataType: "json", contentType: "application/json", success: function( data ) { primer = data.data[0][0].data; Id = data.data[0][1]; label=data.data[0][0].metadata.labels[0]; primer["sid"]=Id; primer["label"]=label; cuenta = data.data[0][2]; nodes.push(primer); actualizaGrafo(); }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, 89 complete: function(data) { } }) } function Nodo1(dato,nodoini){ var consulta11 = { "query" : "START n=node(*) where n."+dato+"='"+nodoini+"' RETURN n, ID(n) ", "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta11), dataType: "json", contentType: "application/json", success: function( data ) { primer = data.data[0][0].data; Id = data.data[0][1]; label=data.data[0][0].metadata.labels[0]; primer["sid"]=Id; primer["label"]=label; cuenta = data.data[0][2]; nodes.push(primer); 90 actualizaGrafo(); }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { } }) } Anexo J. Numvecinos.js //Se llama al dar click sobre un nodo para determinar el numero de vecinos que tiene de acuerdo al facetado local function numVecinos(sid){ var consulta5 = { "query" : "START n=node("+sid+") MATCH n-[re]-x where "+tiposN +" RETURN count(x) ", "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, 91 data: JSON.stringify(consulta5), dataType: "json", contentType: "application/json", success: function( data ) { numVeci=data.data[0][0]; //Si el numero de nodos vecinos es menor al limite definido se cierra el modal de facetado local y se abren los nodos vecinos if(numVeci <= totalimite){ $('#popmodal').modal('hide'); //PedirVecinos pedirVecinos(sid); } //Si el numero de vecinos es mayor se llama al facetado local else{ FacetadoLocal(sid); } }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { } }) } 92 Anexo K. PedirVecinos.js //Esta función es llamada para abrir los nodos vecinos cuando el numero de vecinos es menor al maximo definido pedirVecinos = function(sid){ var consulta = { "query" : "START n=node("+sid+") MATCH n-[re]-x where "+tiposN +" "+tiposR+" RETURN x, ID(x), startnode(re),ID(startnode(re))", "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta), dataType: "json", contentType: "application/json", success: function( data ) { for(i=0; i<data.data.length; i++){ origenind = -100; posfin = -100; insertada=false; linkinser=false; b = data.data[i][0].data; 93 id=data.data[i][1]; label=data.data[i][0].metadata.labels[0]; b["sid"]=id; b["label"]=label; nodoinicio = data.data[i][2].data; idre=data.data[i][3]; nodoinicio["sid"]=idre; abrirVecinos(sid); } actualizaGrafo(); $("g").popover('hide'); tp=0; }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { }})} Anexo L. abrirVecinos.js function abrirVecinos(sid){ //recorre todo el arreglo de nodos que se encuentra almacenado, se compara el identificador de cada elemento almacenado 94 //con el identificador del elemento que se va almacenar si ya esta en el arreglo insertada se pone en true y no se agrega for(j=0; j<nodes.length;j++){ if(nodes[j].sid==b.sid){ insertada=true; posb=j; } } // si insertada esta en false no esta en el arreglo el nodo y se agrega if(insertada==false){ posb=nodes.push(b) - 1; } // Se verifica el nodo inicio de la relacion para determinar la dirección de la misma for(j=0; j<nodes.length;j++) { if(nodes[j].sid==sid && nodoinicio.sid==nodes[j].sid){ origenind=j; posfin = posb; } if(nodes[j].sid==sid && nodoinicio.sid != nodes[j].sid){ origenind=posb; posfin=j; } 95 } //Se verifica que las relaciones no esten en el arreglo para agregarlas for(k=0; k<links.length; k++){ if(links[k].source.sid== nodes[origenind].sid && links[k].target.sid==nodes[posfin].sid) linkinser=true; } if(linkinser==false){ links.push({source: nodes[origenind], target: nodes[posfin]}); } Anexo M. } Cierre.js //Agrega al array de eliminado el nodo pulsado cerrar = function(sid){ borrar = []; borrarVecinos=[]; borrarLinks=[]; //busco posicion del nodo pulsado for(l=0; l<nodes.length; l++){ if(nodes[l].sid==sid){ pulsado=l; } } borrarVecinos.push(nodes[pulsado]); 96 cerrarVecinos(sid,true); actualizaGrafo(); } Anexo N. Cerrar.js function cerrarVecinos(sid,actualiza){ //buscamos y agregamos todos los nodos vecinos del nodo pulsado for( i=0; i<links.length;i++){ if(links[i].target.sid==sid){ borrar.push(links[i].source); } if(links[i].source.sid==sid){ borrar.push(links[i].target); }} for(j=0; j < borrar.length; j++){ linksVecinos = []; //buscamos cuantos links tiene cada vecino for(k=0; k < links.length; k++){ if(links[k].source.sid == borrar[j].sid) linksVecinos.push(links[k]); if(links[k].target.sid == borrar[j].sid) linksVecinos.push(links[k]); } 97 //si el nodo vecino tiene una sola relación correspondiente al que une al nodo pulsado se agrega a los arreglos correspondientes el nodo //y la relación para luego ser eliminados if(linksVecinos.length == 1){ borrarLinks.push(linksVecinos[0]); borrarVecinos.push(borrar[j]); } // en el caso de tener mas de una relación se busca la que une el vecino con el nodo pulsado y agrega al arreglo de relaciones para eliminarse if(linksVecinos.length > 1 && actualiza){ for( a=0; a<links.length;a++){ if(links[a].target.sid==sid && links[a].source.sid == borrar[j].sid){ borrarLinks.push(links[a]); } if(links[a].source.sid==sid && links[a].target.sid == borrar[j].sid){ borrarLinks.push(links[a]); }}}} // Se busca las relaciones que coincidan entre el arreglo que contiene todas las relaciones y el arreglo que contienen las relaciones a eliminarse // y se las elimina for(f=0; f <links.length; f++){ 98 for(p=0; p <borrarLinks.length; p++){ if(borrarLinks[p].source.sid == links[f].source.sid && borrarLinks[p].target.sid==links[f].target.sid){ links.splice(f,1); } }} // Se busca en el arreglo de todos los nodos los que coincidan con los que se encuentran en el arreglo de nodos para eliminar y se los elimina for(n=0; n < nodes.length; n++){ for(g=0; g < borrarVecinos.length; g++){ if(nodes[n].sid == borrarVecinos[g].sid ){ nodes.splice(n,1); }}}} Anexo O. funcionesBotones.js //Asigno a la variable buscar el input text del buscador inicial de nodos buscar= $("#Buscador"); busq=0; //Cuando se selecciona en el buscador una de las opciones de tipo de nodo por el cual buscar $('#idnodo').click(function() { busq=1; }); $('#provincia').click(function() { busq=2; name=$('#provincia').attr('name'); }); 99 $('#canton').click(function() { busq=3; name=$('#canton').attr('name'); }); $('#lengua').click(function() { busq=4; name=$('#lengua').attr('name'); }); // click en el boton buscar $('#PrimerNodo').click(function() { if(busq==0){ alert("Primero elija con el tipo de dato que desea buscar") } // Borramos lo que tenemos en pantalla al realizar nueva busqueda if(links.length != 0){ links.length=0; } if(nodes.length != 0){ nodes.length=0; } //Si se elige IDNodo se llama a la función PrimerNodo ingresando el identificador del nodo if(busq==1){ nodoini=parseInt(buscar.val()); 100 PrimerNodo(nodoini); } //Si se elige un tipo de nodo para buscar por su nombre se llama a la función Nodo1 if(busq != 1 && busq != 0){ //nombre ingresado nodoini=buscar.val().toUpperCase(); //tipo de nodo dato=etiqueta[name]; Nodo1(dato,nodoini); } }); //tooltip guía para la busqueda inicial $('#empezar').tooltip({ 'html':'true', 'placement': 'bottom', 'title':"<div >Para empezar elija el tipo de dato que va a ingresar</div>" }); //tooltip guía para el desplegable de tipo de nodos $('#titnodos').tooltip({ 'html':'true', 'placement': 'bottom', //cambiar texto 101 'title':"<div >Puede elegir el tipo de nodos que desea ver durante la navegación</div>" }); //tooltip guía para los checkbox en el tipo de nodos $('#collapseOne').tooltip({ 'html':'true', 'placement': 'bottom', //cambiar texto 'title':"<div >Si no desea ver un tipo de nodo lo puede deseleccionar </div>" }); //tooltip guía para el desplegable de tipo de relaciones $('#titRelaciones').tooltip({ 'html':'true', 'placement': 'bottom', //cambiar texto 'title':"<div >Puede elegir el tipo de relaciones que desea ver durante la navegación</div>" }); //tooltip guía para los checkbox en el tipo de relaciones $('#collapseTwo').tooltip({ 'html':'true', 'placement': 'bottom', //cambiar texto 102 'title':"<div >Si no desea ver un tipo de relación lo puede deseleccionar </div>" }); Anexo P. facetadoLocal.js //Esta funcion es llamada para abrir el facetado local cuando el numero de nodos es mayor a lo establecido //Obtiene todos los tipos de nodos vecinos y el numero de vecinos que tiene cada tipo function FacetadoLocal(sid){ var consulta6 = { "query" : "START n=node("+sid+") MATCH n-[re]-x where "+tiposN +" RETURN distinct labels(x), count (x)", "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta6), dataType: "json", contentType: "application/json", success: function( data ) { tiposLocal=[]; for(i=0; i<data.data.length;i++){ 103 typ={}; typ["tipo"]=data.data[i][0][0]; typ["nume"]=data.data[i][1]; tiposLocal.push(typ); } $("#mi_div3").empty(); $("#miselec").empty(); $("#mi_div5").empty(); $("#mi_div3").append("<option value='vaciop'>...</option>"); //Rellena el select con todos los tipos de vecinos y el numero de nodos que tiene cada uno for (j = 0; j < tiposLocal.length; j++) { $("#mi_div3").append("<option name='"+tiposLocal[j].nume+"' value='"+tiposLocal[j].tipo+"' >" +tiposLocal[j].tipo+" ("+tiposLocal[j].nume+" nodos) </option>"); } $("#mi_div3").show(); $("#loader1").hide(); sidClick=sid; //Detecta si se elige una opción del select y obtenemos los atributos $("#mi_div3").change(function() { $("#loader2").show(); 104 if($("#mi_div3 option:selected").val()!= 'vaciop'){ $("#mi_div5").empty(); nombre = $("#mi_div3 option:selected").val(); $("#miselec").empty(); numveci=parseInt($("#mi_div3 option:selected").attr('name')); //Si el tipo de nodo elegido tiene un numero menor de nodos al máximo entonces se abren los nodos vecinos del tipo escogido if(numveci<=totalimite){ VecinosMenor(sidClick); $("#mi_div3").empty(); } //Si el número de nodos es mayor entonces llamamos a tiporelaLocales para obtener el siguiente nivel de filtrado else{ tiporelaLocales(sidClick); }} }); }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { } }) } 105 Anexo Q. VecinosMenore.js //esta función es llamada despues de la primera seleccion en el facetado local //al elegir un tipo de nodo vecino que tenga igual o menos vecinos que el limite definido. function VecinosMenor(sid){ var consulta7 = { "query" : "START n=node("+sid+") MATCH n-[re]-x x:"+nombre+" where RETURN x, ID(x), startnode(re),ID(startnode(re))", "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta7), dataType: "json", contentType: "application/json", success: function( data ) { for(i=0; i<data.data.length; i++){ origenind = -100; posfin = -100; insertada=false; linkinser=false; 106 b = data.data[i][0].data; id=data.data[i][1]; label=data.data[i][0].metadata.labels[0]; b["sid"]=id; b["label"]=label; nodoinicio = data.data[i][2].data; idre=data.data[i][3]; nodoinicio["sid"]=idre; abrirVecinos(sid); } actualizaGrafo(); $("g").popover('hide'); tp=0; }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { } }) } 107 Anexo R. tipoRelaLocales.js //Esta función es llamada una vez elegido un tipo de nodo vecino que tenga mas vecinos de los definido como máximo // La consulta realizada nos devuelve el tipo de relaciones que tienen los vecinos de acuerdo al tipo escogido function tiporelaLocales(sid){ var consulta8 = { "query" : "START n=node("+sid+") MATCH n-[re]-x-[r]-(b) WHERE x:"+nombre+" RETURN DISTINCT labels(x), type(r) , labels(b) ", "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta8), dataType: "json", contentType: "application/json", success: function( data ) { tipox=[]; relacionxb=[]; tipob=[]; for(i=0; i<data.data.length; i++){ 108 tx=data.data[i][0][0]; xb=data.data[i][1]; tb=data.data[i][2][0]; tipox.push(tx); relacionxb.push(xb); tipob.push(tb); } $("#miselec").empty(); //Rellena el select con los tipos de relaciones que tiene el tipo de nodo $("#miselec").append("<option value='vacio'>...</option>"); for(c=0; c<relacionxb.length; c++){ $("#miselec").append("<option value='"+tipob[c]+"'>"+relacionxb[c]+"</option>" ); } $("#loader2").hide(); $("#miselec").show(); aplastado=sid; //Al seleccionar un tipo de relacion me obtiene los atributos y llama a la función relacionesLocales //para desplegar los nodos vecinos que tiene el vecino con la relacion elegida $("#miselec").change(function() { $("#loader3").show(); 109 if($("#miselec option:selected").val()!= 'vacio'){ $("#mi_div5").empty(); nombreb = $("#miselec option:selected").val(); relacionesLocales(aplastado); }}); }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { } })} Anexo S. relacionesLocales.js //Esta consulta obtiene los distintos nodos vecinos del vecinos que tengan la relacion elegida y el número de relaciones que tiene function relacionesLocales(sid){ var consulta9 = { "query" : "START n=node("+sid+") MATCH n-[re]-x-[r]-(b) WHERE x:"+nombre+" and b: "+nombreb+" RETURN DISTINCT count (r),b ", "params" : { } }; $.ajax({ async: true, 110 type: "POST", url: enlace, data: JSON.stringify(consulta9), dataType: "json", contentType: "application/json", success: function( data ) { numrelaciones=[]; nodob=[]; for(i=0; i<data.data.length; i++){ nrel=data.data[i][0]; nb=data.data[i][1].data; numrelaciones.push(nrel); nodob.push(nb); } numConsultas=0; totalnumRela=0; $("#mi_div5").empty(); //Muestra en pantalla todos los distintos nodos con su respectivo número de relaciones junto con checkbox for(c=0; c<nodob.length; c++){ $("#mi_div5").append("<div><input type='checkbox' id="+c+"nrl name='"+nodob[c][etiqueta[nombreb]]+"' value='"+numrelaciones[c]+"' >"+nodob[c][etiqueta[nombreb]]+" tiene: "+numrelaciones[c]+" nodos relacionados </div>" 111 ); //Verifica si cada checkbox esta en check o no y los cuenta, de acuerdo a eso es el numero de consultas que se van a realizar con sus respectivos datos $('#'+c+'nrl').click(function(){ contar=$(this); if(contar.is(":checked")){ numConsultas++; } else{ numConsultas--; } pulsa=sid; }); } $("#loader3").hide(); $("#mi_div5").show(); $('#btnSubmitL').show(); //Al dar click sobre el botón vecinos $('#btnSubmitL').click(function() { //Si el nodo pulsado tiene nodos vecinos abiertos los cierra para abrir los nuevos borrar = []; borrarVecinos=[]; borrarLinks=[]; cerrarVecinos(pulsa,false); 112 //divide el limite de nodos que se pueden visualizar para el numero de consultas que se van a realizar //para que cada seleccion tenga el mismo numero de nodos vecinos consulReal=0; limite=Math.ceil(totalimite/numConsultas); nombresNodosb=[]; atributoNombre=etiqueta[nombreb]; for(j=0; j < nodob.length; j++){ nombresNodos={}; var localb = $('#'+j+'nrl').is(":checked"); localbthis=$('#'+j+'nrl'); //Si el checkbox esta en check se obtiene el numero de nodos relacionados if(localb){numnodos=parseInt(localbthis.attr('value')); //Si el numero de nodos relacionados es mayor al limite se mostraran los nodos desde una posicion aleatoria if(numnodos > totalimite){ rando = Math.floor(Math.random() * (numnodos)); if(rando > numnodos - totalimite){ skipe=rando-totalimite; 113 } else{ skipe=rando; } if(skipe<0){ skipe=0; } } else{ skipe=0; } nombresNodos["nodob"]=localbthis.attr('name'); nombresNodos["numero"]=skipe; nombresNodosb.push(nombresNodos); } } //de acuerdo al numero de checkbox que se encuentren en check se realizara el llamado de la funcion VecinosLocales con sus respectivos datos for(k=0; k<nombresNodosb.length; k++){ nodoveci=nombresNodosb[k].nodob; skip=nombresNodosb[k].numero; VecinosLocales(pulsa) $("#mi_div3").empty(); 114 $("#miselec").empty(); $("#mi_div5").empty(); } $("g").popover('hide'); tp = 0; }); }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { } })} Anexo T. VecinoLocales.js //Esta funcion se llama por cada checkbox en check y la consulta devuelve los nodos que cumplan con los datos que se dan en la consulta function VecinosLocales(sid){ var consulta7 = { "query" : "START n=node("+sid+") MATCH n-[re]-x-[r]-(b) where x:"+nombre+" and b:"+nombreb+" and b."+atributoNombre+"='"+nodoveci+"' RETURN x, ID(x), startnode(re),ID(startnode(re)) skip "+skip+" "+limite+"", 115 Limit "params" : { } }; $.ajax({ async: true, type: "POST", url: enlace, data: JSON.stringify(consulta7), dataType: "json", contentType: "application/json", success: function( data ) { for(i=0; i<data.data.length; i++){ origenind = -100; posfin = -100; insertada=false; linkinser=false; b = data.data[i][0].data; id=data.data[i][1]; label=data.data[i][0].metadata.labels[0]; b["sid"]=id; b["label"]=label; nodoinicio = data.data[i][2].data; idre=data.data[i][3]; nodoinicio["sid"]=idre; abrirVecinos(sid); 116 } consulReal++; if(consulReal==numConsultas){ actualizaGrafo(); } }, error: function( xhr ) { print('error retrieving schema'); window.console && console.log( xhr ); }, complete: function(data) { } }) } 117