
Si bien conocía que existían bases de datos no relacionales, quiero compartir mi reciente (y gratificante) experiencia con una de ellas.
Neo4j es una base de datos que utiliza nodos y relaciones entre ellos. A su vez, estas relaciones son capaces de contener sus propias propiedades.
La conexión se establece usando un protocolo propio llamado Bolt. Más adelante, se detalla cómo hace una aplicación para poder comunicarse.
Utiliza un lenguaje propio de consultas Cypher Query, que para los que conocen SQL es bastante similar aunque tiene sus pequeñas características. Se aprende bastante rápido usando como referencia la documentación oficial.
Justamente el otro tema a destacar es la comunidad que da soporte, la documentación es muy completa, tienen videos tutoriales en un canal oficial de YouTube y, si estás suscripto a las notificaciones, todas las semanas estarás recibiendo un correo con las últimas novedades.
Performance
Algo realmente para destacar es la performance. Quiero mostrar un ejemplo que se detalla en su sitio oficial. Se trata de comparar las consultas entre una base de datos relacional (MySql) y Neo4j para cuando en una red social se quiere consultar los amigos de un usuario.
Luego, en cada iteración se agrega un nivel de profundidad. Para un nivel de profundidad 3, la consulta sería; los amigos de los amigos de un usuario.
La siguiente tabla muestra los resultados en segundos para 1.000 usuarios en una base de datos con 1.000.000 de usuarios:
Press enter or click to view image in full size

Neo4j IDE
El IDE de Neo4j Desktop es bastante completo y viene con muchas funcionalidades. Para ser sincero, no he utilizado todas las que tiene.
Lo que más me gusta es la interfaz gráfica de los nodos y las relaciones, y que con sólo hacer unos clicks ya se puede obtener la información que se necesita con el nivel de profundidad/detalle que se desee.
Press enter or click to view image in full size

Neoj4 Cloud
En esta sección quiero mencionar a Neo4j AuraDb, que es la solución que se ofrece para cloud.
Neo4j ofrece su propio servicio de cloud con todas las características: rapidez, capacidad de automatizar procesos, seguridad, high availability, etc.
También posee diferentes planes de contratación que se pueden elegir según la magnitud del proyecto.
Cypher Query Language
Cypher Query es el lenguaje declarativo para poder obtener información de los grafos. Es bastante intuitivo, lo que lo hace fácil de aprender.
Lo que busca es, que usando caracteres ASCII, se tenga una representación visual de la consulta que quiere realizarse. Entonces, en la siguiente sentencia: (nodes)-[:ARE_CONNECTED_TO]->(otherNodes) se puede observar que los nodos son representados con paréntesis y las relaciones con el formato -[]->.
El símbolo > indica la dirección de la relación. Es decir, cuál es el origen y el destino. Para consultar cuáles son los que se conectan con uno, puede definirse la sentencia: (nodes)<-[:ARE_CONNECTED_TO]-(otherNodes)
Para saber cómo es la estructura de una consulta y cómo se ejecutan, les recomiendo leer el manual que cuenta con muchísimos ejemplos. (En la última sección de este artículo hay un ejemplo de código que ejecuta una consulta).
Lo que sí quiero destacar es que comparado con una sentencia SQL de una consulta con varios JOINS en una base de datos relacional, la misma consulta hecha en Cypher Query, puede reducir las líneas de código y esto hará que sea más fácil de mantener.
De relacional a grafos
¿Qué ocurre si venimos trabajando hace años con bases de datos relacionales y, por más que leamos y practiquemos, cuesta un poco empezar a entender los grafos?
La verdad es que esto sucede y es una realidad. La transición de pasar de bases de datos relacionales a una base de datos con grafos es una tarea algo incómoda en un principio.
Algunos pasos recomendados en este vídeo para convertir una base relacional a una de grafos es:
- Localizar y eliminar todas las foreign keys. Reemplazarlas por relaciones.
- Localizar las tablas de JOIN. En caso que sean simples (sólo los campos IDs), reemplazarlas por relaciones. En caso que posean otros campos, serán convertidas a relaciones también, pero esos campos serán propiedades de esta nueva relación.
¿Existen ventajas para usar bases de datos grafos sobre relacionales?
Hay algunas consideraciones que pueden tenerse en cuenta para decidir utilizar una base de grafos:
- Es más fácil modelar y almacenar relaciones.
- Las consultas son más cortas y más legibles.
- Nodos y relaciones pueden ser agregados on-the-fly. Migraciones no son necesarias.
- Manejo de índices: con Index-free adjacency, cada nodo hace referencia directamente a sus nodos adyacentes, actuando como un micro-índice para todos los nodos cercanos. Esto es lo que hace que las consultas sean más eficientes. Para una explicación en detalle, recomiendo que lean este artículo.
Neo4j Driver
¿Qué ocurre si tenemos una aplicación y queremos que nuestro origen de datos sea Neo4j?
Podemos conectarla a través de Neo4j driver. El mismo se encuentra disponible para Go, Python, Java, Javascript y .NET.
En la siguiente sección, mostraré un ejemplo de código de cómo ha sido implementado en una aplicación con .NET Core.
Existe otro componente que puede ser utilizado para la misma funcionalidad llamado Neo4jClient. En un foro oficial, un usuario consultó cuál era la diferencia entre utilizar uno u otro. La respuesta fue la siguiente:
- No existe diferencia de performance entre ambos.
- Si trabajas con un equipo grande y la complejidad de la aplicación es significante, conviene utilizar Neo4jClient. (Posee algunos extension-methods que hace que la forma de escribir consultas sea con expresiones lambda, por lo que hacer code-review o mantener el código sería más fácil).
- Si solo deseas ejecutar consultas rápidamente, conviene Neo4j.Driver.
Un poco de código
Voy a mostrar un ejemplo de código en C# que conecta una aplicación con un origen Neo4j.
En primer lugar, en el archivo de configuración appsettings.json se define una sección Neo4jSettings que posee la URL, User & Password.
"Neo4jSettings": {
"Address": "bolt://localhost:7687",
"User": "neo4j",
"Password": "password"
}
Vamos a definir una clase que represente a esta sección
public class Neo4jSettings
{
public string Address { get; set; }
public string User { get; set; }
public string Password{ get; set; }
}
El siguiente paso consiste en configurar y registrar el Driver como singleton en Startup.cs
public void ConfigureServices(IServiceCollection services) { ... var neo4jSettings = new Neo4jSettings(); Configuration .GetSection("Neo4jSettings") .Bind(neo4jSettings); var token = AuthTokens .Basic(neo4jSettings.User, neo4jSettings.Password); services.AddSingleton(GraphDatabase .Driver(neo4jSettings.Address, token)); ... }
Por último, será inyectada en nuestras clases de acceso a datos.
public class PersonDataAccess : IPersonDataAccess { public IDriver Driver { get; } public PersonDataAccess(IDriver driver) { Driver = driver; } public IEnumerable<PersonDTO> GetAll() { using (var session = this.Driver.AsyncSession()) { var query = new Query(@$" MATCH (x:PERSON) RETURN x"); var cursor = session.RunAsync(query); cursor.Wait(); var result = cursor.Result .ToListAsync(person => MapDTOFromRecord(person)); result.Wait(); return result.Result; } } private PersonDTO MapDTOFromRecord(IRecord record) { var node = record["x"].As<INode>(); return new PersonDTO() { Id = node.Id, Name = node.Properties["Name"].As<string>() }; } }
Bibliografía
https://www.youtube.com/c/neo4j
Cypher Query Language – Developer Guides
Cypher is Neo4j’s graph query language that lets you retrieve data from the graph. It is like SQL for graphs, and was…
neo4j.com
The Neo4j Cypher Manual v4.4 – Neo4j Cypher Manual
© 2021 Neo4j, Inc. This is the Cypher manual for Neo4j version 4.4, authored by the Neo4j Team. This manual covers the…
neo4j.com
Neo4j in Action
By Jonas Partner, Aleksa Vukotic, and Nicki Watt Publisher: Manning Publications Databases are easier to develop and…
neo4j.com