Neo4J - segunda parte

En la primera parte vimos ya cómo se almacenan nodos y sus relaciones en una base de datos de Neo4J. En esta segunda parte veremos cómo hacer búsquedas sobre los nodos, basados en las relaciones que hay.

A estas alturas es importante mencionar que las relaciones en Neo4J son unidireccionales; van de un nodo a otro. Pero no es necesario crear relaciones en el sentido opuesto si no es necesario, ya que se pueden buscar las relaciones indicando el sentido de las mismas. Para esto hay que considerar que la dirección se define desde el nodo que estamos utilizando.

En el ejemplo anterior simplemente fijé el status con la relación  , pero fuera de eso no hay manera de saber si el usuario ya tenía un status previo, y no hay manera sencilla de encontrar el status más reciente. Por ello, es mejor agregar un nuevo tipo de relación,  , y solamente manejar una sola relación de cada usuario hacia un status. Si encapsulamos esto en un método de un DAO puede quedar así:

 

Del mismo modo podemos hacer un método para marcar que a un usuario le gusta el status de otro usuario:

 

Con lo anterior, cada vez que queramos cambiar el status de un usuario solamente tenemos que llamar por ejemplo   o  .

Ahora, vamos a mostrar el status del usuario u1 y los "likes" marcados por otros usuarios:

 

Envoltorios / ORM

Bueno y qué pasa si quieren tener clases Usuario, Foto, Status? Lo que se puede hacer es crear clases que funcionen como envoltorios y que manejen su nodo internamente:

 

Esto junto con un DAO que maneje ciertas búsquedas, altas, modificaciones etc y obtenga los nodos y los envuelva en la clase correspondiente, puede darnos un poco de abstracción.

Una alternativa más simple de manejar nodos envueltos en objetos es el framework jo4neo, que se basa en anotaciones muy simples para manejar las propiedades de un nodo como propiedades de un objeto en Java. Usando jo4neo, la clase Status quedaría así, con menos código:

 

Jo4neo ofrece además algunas facilidades para búsquedas. Esto se puede ver en la página del proyecto.

Búsquedas de texto

Por lo general, las aplicaciones que utilizan una base de datos de grafos no se enfocan tanto a búsquedas muy complejas basadas en los valores de un nodo, sino más bien se recorren las relaciones y se hacen ciertas búsquedas simples por las relaciones entre nodos. Sin embargo, siguiendo el ejemplo de nuestra chafanet social, deberíamos poder buscar usuarios por su nombre o correo electrónico.

Una opción para esto es almacenar en una base de datos relacional solamente los emails junto con una liga hacia el ID del nodo que representa al usuario; esto nos permite buscar si ya existe un usuario con cierto email para evitar duplicados, o bien encontrar usuarios basados en su email. Pero entonces para cada dato hay que tener la información replicada; si el usuario cambia de email o desea editar su nombre, hay que cambiar los datos en el nodo Y en la tabla relacional, o bien armar el objeto que representa al Usuario a partir de dos fuentes de información (el nodo y la tupla relacional), lo cual dificulta el mantenimiento de los datos.

Otra opción que nos da Neo4J es el IndexService, que es simplemente una interfaz que define los mecanismos de búsqueda disponibles. Se puede implementar un backend con base de datos relacional (similar a lo que mencioné en el párrafo anterior), o bien se puede usar el LuceneIndexService o LuceneFullTextIndexService, ambos basados en Apache Lucene, y que no son mutuamente excluyentes.

Un ejemplo sencillo para indexar todo lo que se ha ilustrado hasta ahora:

 

El LuceneFullTextIndexService es similar pero hace búsquedas de texto completo, que se prestan más para buscar por aproximaciones. Por ejemplo   con la búsqueda de texto completo nos devolvería los 3 usuarios ya que todos contienen esa palabra en el nombre (Usuario Uno, Usuario Dos, Usuario Tres).

En fin, esta página contiene mayor información respecto a los servicios de índices con Lucene, y además como mencioné en la sección anterior, jo4neo tiene también algunas facilidades para realizar búsquedas simples entre nodos.

Componentes adicionales

Hay varios componentes adicionales a la base de datos, como por ejemplo implementaciones de algoritmos para encontrar la ruta más corta entre dos nodos o encontrar el nodo más céntrico en una red; bindings para usar neo4j con Ruby o Python; conectores para tener acceso a una base de neo4j que corre en un proceso separado (aunque este último necesita bastante optimización todavía); un shell para acceder a una base de datos desde línea de comando; una capa alrededor de Neo4j para manejar la base de datos con RDF.

En lo personal creo que para ciertas aplicaciones muy específicas, Neo4J puede servir bastante bien y simplificar el trabajo cuando las relaciones entre datos son tan importantes como los datos mismos, pero no creo que sirvan como reemplazo de una base de datos relacional, al menos por ahora.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de rodrigo salado anaya

muy buena tanto..

tanto como la 1ra parte, igual de interesante!!

Buen informe

A ver que proyectos puedo hacer usando esta tecnologia :)

Imagen de ezamudio

Es alrevés...

No se trata de que busques qué proyectos hacer donde puedas usar esta tecnología (o cualquier otra). Simplemente es bueno que la conozcas y sepas de su existencia para que si algun día necesitas una base de datos de este tipo, recuerdes que existe y puedas revisar aquí cómo se usa...

Creo que se presta para resolver problemas muy específicos. No es una panacea, no es sustituto de una base de datos relacional ni nada por el estilo; creo que un sistema que necesite de esto, podrá usar Neo4J como uno de sus componentes para almacenar ciertos datos, pero eso no va a eliminar la necesidad de una base de datos relacional; incluso por mucho que caigas en el juego de la moda de NoSQL y no quieras usar Oracle/SQLServer/PostgreSQL/MySQL/etc, probablemente tendrás que usar algo como Cassandra o HBase. Espero tener tiempo próximamente de jugar un poco con Cassandra para escribir al respecto.

Imagen de luxspes

Encontrando el ultimo Status escrito por un Usuario en Rel

En el ejemplo anterior simplemente fijé el status con la relación Owns, pero fuera de eso no hay manera de saber si el usuario ya tenía un status previo, y no hay manera sencilla de encontrar el status más reciente. Por ello, es mejor agregar un nuevo tipo de relación, CurrentStatus, y solamente manejar una sola relación de cada usuario hacia un status.

En Rel, no es necesario crear una nueva relación, podemos escribir (siguiendo el modelo definido aqui):

 

Eso nos dara el ultimo Status para el que el Usuario "Juan" es "Autor"

Por fechas seria algo como:

 

Imagen de luxspes

El ultimo status un usuario y los likes de los otros:

Ahora, vamos a mostrar el status del usuario u1 y los "likes" marcados por otros usuarios:
 

En Rel, la consulta equivalente seria:

 

Cual les parece mas corto? ;-)

Ahora que lo pienso... no es exactamente la misma cosa, yo uso IdStatus, un entero consecutivo, en ves de una Fecha para determinar al status mas reciente, supongo que entonces el query quedaria asi:

 

Mmmm, tal ves ya no es tan significativamente mas corto... aunque hay que tomar en cuenta que mi conocimiento de Rel es mas bien superficial y utilice "aliases" largos para hacer mas legibile el codigo... tal ves haya forma de escribirlo de un modo mas corto... cosa de practicar supongo... (y siempre puede ponerse el código dentro de un   para evitar escribirlo una y otra ves) por otro lado, gracias a la propiedad de cerradura, puedo seguir encadenando este query y hacerlo mas especifico (o "joinearlo" con alguno otra relvar). Por ejemplo obtener el conteo total de registros es facil:

 

existe un modo de hace eso en Neo4J (sin tener que cargar todos los nodos y contarlos en mi aplicación cliente? Pasar una especificacion de un query complejo al "servicio" de Neo4J y obtener solo el resultado final?

Imagen de ezamudio

No

Neo4J no es relacional y no tiene un lenguaje de queries. Trabajas directamente con los nodos y sus relaciones. Rel es una base de datos relacional (verdaderamente relacional o como le quieran decir), es una supuesta mejora sobre las RDBMS tradicionales y SQL, y por lo tanto la manera de trabajar es distinta, más similar a SQL.

Imagen de luxspes

Igual podria tener lenguage de queries y ser orientada a grafos

Neo4J no es relacional y no tiene un lenguaje de queries.

Ok, aunque podría ser no relacional e igual si tener un lenguaje de queries ;-) O tener un API como la "Criteria API" de Hibernate... o algo asi... no? (Y si no la tiene... tal vez seria bueno proponerles que le pusieran una... podría quizá ayudar en ciertos casos?)

Imagen de luxspes

SPARQL: un lenguage de queries orientado a grafos para Neo4J!

Esta por ejemplo, SPARQL.... segun la pagina de Neo4J:

Optional layers to expose Neo4j as an RDF store, i.e. easily inject / extract data as RDF, express meta model semantics using OWL and query the node space using SPARQL.

Asi que aparentemente se puede consultar al "espacio de nodos" usando SPARQL... Me pregunto si se podría definir algo equivalente a restricciones con el...

Imagen de ezamudio

Externos

SPARQL y lo de RDF, o la otra opción de usar REST, son ya frameworks externos, que si bien pueden ayudar a Neo4J, no son actualmente parte del paquete y por eso me abstuve de mencionarlos. De hecho iba a omitir la mención de jo4neo (porque además la verdad es que no lo he usado, hice mis propios envoltorios y DAOs), pero me pareció lo suficientemente sencillo como para poder incluirlo.

Y otro punto importante que no mencioné, que habría que comparar con Rel porque puede ser un factor muy importante en ciertas apicaciones: Neo4J tiene una licencia dual, lo puedes usar para software libre sin costo alguno, o para aplicaciones comerciales tienen tres tipos de licencia comercial que incluyen distintos niveles de soporte y características adicionales. Yo me di cuenta de esto ya más tarde y estoy evaluando si continúo el uso de Neo4J o mejor cambio por otra cosa que tal vez sea un poco más complicada de usar pero que pueda usar sin estas restricciones; cambiar a un modelo relacional va a estar de flojera pero gracias a un buen diseño inicial, "solamente" tengo que reescribir la parte que guarda datos en Neo4J para que los guarde en otra cosa y el resto de la aplicación sigue intacto.

Imagen de ezamudio

Licencias y otros aspectos

Ya revisé y Rel usa APL 2.0, lo cual permite su uso en aplicaciones comerciales. Estaría a punto de decir "Game over. Rel wins"... pero está en versión 0.3 Alpha, lo cual significa que está muy pero muy lejos de que la pueda siquiera considerar para una aplicación seria. Y al echarle un ojo a las limitaciones, bueno... es muy bonita la teoría pero no le puedes vender teoría a un cliente (ni apostarle si vas a hacer aplicaciones para tu propia empresa). Usan BDB, que no soporta transacciones anidadas y están considerando cambiar de motor de almcenamiento, muy probablemente por uno propio.

Como tal ya no mencionan nada más acerca de respaldos ni replicación ni nada de esto; supongo que al usar BDB se lavan las manos y ya no depende de Rel sino de BDB. Neo4J soporta respaldos en línea, lo cual es bastante bueno; hasta donde recuerdo (por el uso de Subversion), BDB no soporta eso como tal. Y con base en el respaldo en línea, Neo4J soporta también replicación, aunque sea emulada, donde puedes tener un maestro y varios esclavos de sólo lectura.

Desconozco el grado de soporte que haya para Rel, pero viendo la página no me parece que sea muy fuerte por el momento. En contraste, neo4j tiene soporte comercial (por lo de las licencias) y parece tener una comunidad de buen tamaño para el soporte a aplicaciones de software libre. En general me da la impresión que Rel está naciendo apenas y aunque se ve muy bien y promete bastante, no es algo que se pueda usar hoy en un sistema en producción, de hecho ni siquiera empezarse a usar con su versión actual esperando que dentro de 6 meses que termines tu sistema, Rel ya esté listo para producción.

En fin, querías una comparación, y creo que ese tipo de características también son muy importantes cuando se comparan productos distintos; no solamente la sintaxis o el número de líneas de código que hay que escribir. Ponerle restricciones a una relación en particular tal vez no lo tenga neo4j pero se lo pones en un DAO y funciona aunque sea a nivel aplicación, pero a los otros aspectos que mencioné creo que no hay manera de darles la vuelta. Cada uno tiene ventajas y desventajas (para mi, pesa mucho el rollo de las licencias).

Imagen de luxspes

En terminos de licencias y otros aspectos, gana Neo4J

Totalmente de acuerdo, en términos de licencia, respaldos, replicacion, etc, gana Neo4J. Aunque no me sorprende: Oracle, MSSQL, MySQL, PostgreSQL y Db2 también le ganan a Rel (y a Neo4J) en mucho de estos aspectos. Mi comparación iba mas orientada al uso de directo de las facilidades del producto para realizar algún trabajo (desde mi primer post de Rel aclare que su "objetivo principal de Rel es como una herramienta de enseñanza"):


Rel es básicamente un proyecto académico, construido con la intención mas bien de enseñar y no ser utilizando (asi como esta ahorita) directamente en producción para un sistema del mundo real...

Pero estoy de acuerdo en que efectuar esta otra comparación que haces tu es valioso (después de todo, yo mismo no recomendaría Rel para un entorno de producción hasta que no alcance madurez en estos sentidos). Por otro lado ¿que pasa con los costos ocultos (por bugs y tiempo de desarrollo utilizado) que tienen productos como Neo4J (o Oracle, MSSQL, MySQL, PostgreSQL y Db2 ) debido a que sus APIs estan pobremente diseñadas?... Siento que ese es un aspecto de estos productos que se ha descuidado, y por eso creo que tambien puede ser valioso analizar esa parte.

Imagen de ezamudio

Costo

Es difícil calcular dichos costos. Por un lado tienes que evaluar esos costos de estarte peleando con defectos del producto que utilices (sea el que sea, Rel, Neo4J, Cassandra, Oracle, SQLServer, PostgreSQL, MySQL, Db2, etc), que son tiempo de desarrollo perdido y que puede impactar de distintas formas (desde pagar más horas de un programador o consultor externo hasta tener que cambiar de RDBMS a mitad del proyecto por un defecto que no se le puede dar la vuelta, o perder el proyecto entero porque ya se pasó la fecha de entrega, el cliente se desespera, etc).

Por otra parte tienes que evaluar cuál es el costo de que se pierda toda la información almacenada desde el último respaldo, porque no se pueden hacer respaldos en línea y entonces hay que programarlos en las noches/fines de semana/etc en ventanas de mantenimiento junto con otras tareas; el costo de que empiece a haber inconsistencias en datos, se pierda la integridad de la información, etc (cosa que ya es muy raro que pase las RDBMS que hemos mencionado, incluso en MySQL que considero el más chafa de todos).

También hay que evaluar no solamente costos, sino riesgos... cuál es el riesgo de que el producto que estás usando sea abandonado a medio proyecto? O que decidan supermejorarlo y hacer una versión nueva, abandonando la actual por completo (soporte, bugs, etc) y que la nueva sea totalmente incompatible con la que estás usando?

Finalmente, y esto es simplemente una pregunta que dejo al aire: cuál es la finalidad de usar Rel como software para enseñar, si no existe un solo producto en el mercado que utilice sus principios? qué es lo que se enseña con eso? simplemente que todas las RDBMS son una porquería porque no son verdaderamente relacionales? que SQL apesta, pero no hay alternativa? Ya casi casi me suena a que Rel fue un complot de la banda de NoSQL para echarle tierra a las bases de datos relacionales y, al no haber alternativa, jalar más gente a su campo (que también creo que actualmente está sobrevalorado, y opino muy similar a lo que dijo Ted Dziuba recientemente).

Imagen de luxspes

BDB: Tampoco esta tan mal.

Como tal ya no mencionan nada más acerca de respaldos ni replicación ni nada de esto; supongo que al usar BDB se lavan las manos y ya no depende de Rel sino de BDB. Neo4J soporta respaldos en línea, lo cual es bastante bueno; hasta donde recuerdo (por el uso de Subversion), BDB no soporta eso como tal. Y con base en el respaldo en línea, Neo4J soporta también replicación, aunque sea emulada, donde puedes tener un maestro y varios esclavos de sólo lectura.

Bueno segun NoSQL:

Berkeley DB: API: Many languages, Written in: C, Replication: Master / Slave, Concurrency: MVCC, License: Sleepycat, Berkeley DB Java Edition: API: Java, Written in: Java, Replication: Master / Slave, Concurrency: serializable transaction isolation, License: Sleepycat.

Asi que el que Rel use a BDB como store tampoco esta tan mal ;-). Tiene Concurrency: MVCC, y tiene Replicacion (claro que hace hace falta exponer esos servicios desde Rel, pero no es un mal inicio)

Error, de mi parte, NoSQL se refiere a la BDB basada en C, no a la basada en Java :-(

Imagen de luxspes

Rel no es el unico, es el basado en Java (y esto es JavaMexico)

Finalmente, y esto es simplemente una pregunta que dejo al aire: cuál es la finalidad de usar Rel como software para enseñar, si no existe un solo producto en el mercado que utilice sus principios?

Bueno, del lado de .NET (y tambien Opensource) esta Dataphor, Ingres esta pensando en adoptar el lenguaje Tutorial D para futuras versiones y hay varios otros esfuerzos en la dirección de verdaderas RDBMS. Esta inclusive AlgebraixData que va mas alla del modelo relacional (usando la teoria de conjuntos extendido). Yo solo hablo aquí de Rel, por que este sitio es javamexico y Rel esta construido sobre Java.

La finalidad es poder mostrarle a la gente que SQL no es lo mismo Relacional, y que todavía estamos por construir una base de datos relacional (y que seria interesante y valioso construir una por que haria varias tareas mas fáciles y menos propensas a errores). Por eso es importante aclarar la diferencia entre SQL y Relacional, por que si se confunden, cuando alguien oiga de Rel pensara "ah, es otra base de datos SQL mas como Oracle, PostgreSQL,etc, etc" y no es asi.

Por otro lado, entiendo a todas las "DBMS basadas en SQL" la industria se acostumbro a llamarlas "RDBMS" (aunque no se hubieran ganado la totalidad de la R). Pensando en ello tal ves seria mejor referirse a Rel como TRDBMS

Imagen de luxspes

Ja: No creo que Rel sea un complot de NoSQL ;-)

Ya casi casi me suena a que Rel fue un complot de la banda de NoSQL para echarle tierra a las bases de datos relacionales y, al no haber alternativa, jalar más gente a su campo (que también creo que actualmente está sobrevalorado, y opino muy similar a lo que dijo Ted Dziuba recientemente).

Jajajajja, no creo que Rel sea parte de un complot de NoSQL, pero coincido con Ted Dziuba y contigo: "NoSQL will never die, but it will eventually get marginalized, like how Rails was marginalized by NoSQL. In the meantime, DBAs should not be worried, because any company that has the resources to hire a DBA likely has decision makers who understand business reality."

Rel no puede ser del movimiento NoSQL por que el movimiento NoSQL es "no-relacional", según su propia definición: " Next Generation Databases mostly address some of the points: being non-relational, distributed, open-source and horizontal scalable. " (enfasis mio). Por otro lado, sospecho que dentro de dicho movimiento no tienen una distinción clara entre "Relacional" y "SQL" (yo mismo no conocía la diferencia hasta hace unos pocos meses cuando lei The Third Manifesto). Es precisamente por esa confusión que considero que vale la pena "promocionar" a Rel: Para ver si a otros les da curiosidad y deciden participar o crear proyectos cuyos lenguajes de consultas estén basados en un grado mas completo (o completamente) en los principios del modelo relacional.

Mira por ejemplo a lenguajes como SPARQL, JPAQL o JDOQL, mucho de su diseño esta basado en SQL simplemente por que fue influenciado por la existencia de SQL, no por que fuera el mejor diseño.... sospecho que si hubieran leido The Third Manifesto (o se hubieran visto expuestos a Rel) antes de diseñar esos lenguajes, seria mas cómodos y mas potentes... quiza me equivoque, pero creo que que vale la pena hablar del tema y ver que pasa ;-)