Cypher - Cómo recuperar datos

jueves, 17 de abril de 2014

En anteriores post ya hemos visto una introducción a Neo4jla instalación y un primer vistazo a Neo4j Browser y cómo crear datos con Chyper. En esta ocasión vamos a ver cómo podemos recuperar datos con Cypher.

Clausula Start

Es una clausula opcional desde la versión 2.0, antes esta clausula era obligatoria.

Se utiliza para indicar el punto o los puntos de partida de un query. Ahora si no se especifica, Neo4j intentará inferir los puntos de partida de la query mediante los Labels y los predicados de la query.

Neo4j asigna un Identificador a cada nodo que se crea, este Id se puede usar para indicar un nodo como punto de partida de una query.

Si por ejemplo queremos especificar nosotros un punto de partida especifico es posible hacer referencia a un nodo mediante su id.
start n=node(0) return n

Pero sin embargo Neo4j reutiliza sus identificadores internos cuando se eliminan los nodos y las relaciones, lo que significa que es una mala práctica referirse a ellos de esta manera. En su lugar se recomienda generar identificadores propios y almacenarlos en el nodo como propiedades.

Otro de los usos que podemos dar a la clausula START es cuando queremos identificar puntos de partida haciendo uso de Full-Text Index, pero para no extenderme mucho más con la clausula START ya que es opcional, os dejo un enlace a un post Full-Text-Indexing (FTS) in Neo4j 2.0 de Michael Hunger, donde habla sobre este tema.

Clausula Match

Es la forma principal de obtener datos en Neo4j.

Esquema de una query

El esquema de una query con Match recuperar datos con Cypher es:
MATCH (n)
RETURN n

Con la clausula Match especificamos un patrón a cumplir, en este caso simplemente no indicamos nada o lo que es lo mismo que sea un nodo cualquiera. Esta es la estructura de búsqueda más básica. En Neo4j como ya hemos visto en anteriores post, el tiempo de respuesta de una query depende del recorrido a realizar no del volumen de datos, por esto es fundamental tener el inicio del recorrido lo más acotado posible.

En el ejemplo anterior recorreríamos todos los nodos y devolveríamos todos los nodos. Con un grafo muy grande este tipo de consulta no es recomendable.

Match con Filtros de Labels

En la clausula Match podemos especificar Labels acotando el tipo de nodo a devolver
MATCH (user:User)
RETURN user

Esta query nos devolvería todos los usuarios de la base de datos

Match con Filtros de propiedades

En la clausula Match podemos especificar filtros de propiedades
MATCH (user:User{ name:'user 1' })
RETURN user

Esta query nos devolvería todos los usuarios con el nombre 'user 1'

Match con Filtros de relaciones

En la clausula Match podemos especificar filtros de relaciones
MATCH (user:User{ name:'user 1' })-[:BUY]->(p)
RETURN user,p

Esta query nos devolvería todos los usuarios con el nombre 'user 1'  y los productos que han comprado.

Clausula Where

Sirve para filtrar los resultados del subgrafo a crear para una query

Esquema de una query

El esquema de una query con Where recuperar datos con Cypher es:
MATCH (n)
WHERE n.propiedad = 'valor'
RETURN n

Con la clausula Where filtramos los resultados

Where con Filtros de Labels

En la clausula Where podemos especificar Labels acotando el tipo de nodo a devolver
MATCH (user)
WHERE user:User
RETURN user

Esta query nos devolvería todos los usuarios de la base de datos

Where con Filtros de propiedades

En la clausula Where podemos especificar filtros de propiedades
MATCH (user:User)
WHERE user.name = 'user 1'
RETURN user

Esta query nos devolvería todos los usuarios con el nombre 'user 1'

Match con Filtros de relaciones

En la clausula Match podemos especificar filtros de relaciones
MATCH (user),(p)
WHERE user:User and user.name = 'user 1' and user-[:BUY]->(p)
RETURN user,p

Esta query nos devolvería todos los usuarios con el nombre 'user 1'  y los productos que han comprado.

Resumen

Hemos visto la clausula Start que no es obligatoria y las clausulas Match y Where. En la clausula Match se pueden poner más de un patrón con comas y en la clausula Where no se pueden poner comas pero si con operadores and y or. Match y Where pueden parecer parecidas porque pueden generar el mismo resultado en queries utilizando ambos, pero sus objetivos son totalmente diferentes

Si vemos estos dos ejemplos:

MATCH (user:User{ name:'user 1' })-[:BUY]->(p)
RETURN user,p

MATCH (user),(p)
WHERE user:User and user.name = 'user 1' and user-[:BUY]->(p)
RETURN user,p

En la primera query se genera un subgrafo de los nodos que que cumplen el patrón Match, en el segundo sin embargo, se genera un subgrafo con todos los nodos y se eliminan los que no cumplen el patrón Where. Por lo tanto la primera query es más optima que la segunda.

¿Entonces cuando utilizamos la clausula where?

Pues un poco de sentido común, lo normal es declarar el patrón de búsqueda principal en el Match y luego con el Where hacer un refinamiento del grafo a tratar.

Siento que me quedan muchas cosas por contar de Neo4j y Cypher, pero la idea era hacer unos post de introducción que no quedarán excesivamente largos y que fueran una introducción.

El manual de Neo4j es bastante completo, así que recomiendo que recurráis a el para profundizar.

Tengo en mente hacer futuros post planteando ejemplos más complejos y mas orientado a problemas reales para los que neo4j es realmente bueno.

Libros Relacionados

Graph Databases
Neo4j in Action
A Programmatic Introduction to Neo4j

1 comentario:

  1. Muchas gracias, quería hacer una recuperacion de datos de mi equipo y tu ayuda me ha venido de perlas!

    ResponderEliminar