Extensiones de openCypher en Amazon Neptune - Amazon Neptune

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Extensiones de openCypher en Amazon Neptune

Amazon Neptune es compatible con la versión 9 de referencia de la especificación de openCypher. Para obtener más información, consulte Conformidad con la especificación de openCypher en Amazon Neptune en Amazon Neptune. Además, Amazon Neptune es compatible con las características que se indican aquí. A menos que se mencionen versiones específicas, las características están disponibles en Neptune Database y Neptune Analytics.

La función join() específica de Neptune

Disponible en Neptune Database y Neptune Analytics.

Neptune implementa una función join() que no está presente en la especificación de openCypher. Crea un literal de cadena a partir de una lista de literales de cadena y un delimitador de cadenas. Adopta dos argumentos:

  • El primer argumento es una lista de literales de cadena.

  • El segundo argumento es la cadena delimitadora, que puede tener cero, uno o más caracteres.

Ejemplo:

join(["abc", "def", "ghi"], ", ") // Returns "abc, def, ghi"

La función removeKeyFromMap() específica de Neptune

Disponible en Neptune Database y Neptune Analytics.

Neptune implementa una función removeKeyFromMap() que no está presente en la especificación de openCypher. Elimina una clave específica de un mapa y devuelve el nuevo mapa resultante.

La función toma dos argumentos:

  • El primer argumento es el mapa del que se debe eliminar la clave.

  • El segundo argumento es la clave que hay que eliminar del mapa.

La función removeKeyFromMap() resulta especialmente útil en situaciones en las que se desean establecer valores para un nodo o una relación presentando una lista de mapas. Por ejemplo:

UNWIND [{`~id`: 'id1', name: 'john'}, {`~id`: 'id2', name: 'jim'}] as val CREATE (n {`~id`: val.`~id`}) SET n = removeKeyFromMap(val, '~id')

Valores de identificadores personalizados para las propiedades de los nodos y las relaciones

Disponible en Neptune Database 1.2.0.2 y posteriores y en Neptune Analytics.

A partir de la versión 1.2.0.2 del motor, Neptune ha ampliado la especificación de openCypher para que pueda especificar los valores id para los nodos y las relaciones en las cláusulas CREATE, MERGE y MATCH. Esto le permite asignar cadenas fáciles de usar en lugar de generadas por el sistema UUIDs para identificar nodos y relaciones.

En Neptune Analytics, los valores de ID personalizados no están disponibles para los bordes.

aviso

Esta extensión de la especificación de openCypher no es compatible con versiones anteriores, ya que ahora ~id se considera un nombre de propiedad reservada. Si ya utiliza ~id como propiedad en sus datos y consultas, tendrá que migrar la propiedad existente a una nueva clave de propiedad y eliminar la antigua. Consulte Qué hacer si actualmente utiliza ~id como propiedad.

A continuación, tenemos un ejemplo que muestra cómo crear nodos y relaciones con identificadores personalizados:

CREATE (n {`~id`: 'fromNode', name: 'john'}) -[:knows {`~id`: 'john-knows->jim', since: 2020}] ->(m {`~id`: 'toNode', name: 'jim'})

Si intenta crear un identificador personalizado que ya esté en uso, Neptune mostrará un error DuplicateDataException.

A continuación, se muestra un ejemplo del uso de un identificador personalizado en una cláusula MATCH:

MATCH (n {`~id`: 'id1'}) RETURN n

A continuación, se muestra un ejemplo del uso de la personalización IDs en una MERGE cláusula:

MATCH (n {name: 'john'}), (m {name: 'jim'}) MERGE (n)-[r {`~id`: 'john->jim'}]->(m) RETURN r

Qué hacer si actualmente utiliza ~id como propiedad

Con la versión 1.2.0.2 del motor, la clave ~id de las cláusulas de openCypher ahora se trata como id y no como una propiedad. Esto significa que si tiene una propiedad denominada ~id, es imposible acceder a ella.

Si utiliza una propiedad ~id, lo que debe hacer antes de actualizarla a la versión del motor 1.2.0.2 o posterior es migrar primero la propiedad ~id existente a una nueva clave de propiedad y, a continuación, eliminar la propiedad ~id. Por ejemplo, la siguiente consulta:

  • Crea una nueva propiedad denominada 'newID' para todos los nodos,

  • copia el valor de la propiedad '~id' en la propiedad 'newId'

  • y elimina la propiedad '~id' de los datos.

MATCH (n) WHERE exists(n.`~id`) SET n.newId = n.`~id` REMOVE n.`~id`

Se debe hacer lo mismo con cualquier relación en los datos que tenga una propiedad ~id.

También tendrá que cambiar las consultas que esté utilizando que hagan referencia a una propiedad ~id. Por ejemplo, esta consulta:

MATCH (n) WHERE n.`~id` = 'some-value' RETURN n

...se convertiría en esto:

MATCH (n) WHERE n.newId = 'some-value' RETURN n

Soporte de subconsultas CALL en Neptune

Disponible en Neptune Database 1.4.1.0 y posteriores y en Neptune Analytics.

Amazon Neptune admite subconsultas CALL. Una subconsulta CALL es una parte de la consulta principal que se ejecuta en un ámbito aislado para cada entrada de la subconsulta CALL.

Por ejemplo, supongamos que un gráfico contiene datos sobre personas, sus amigos y las ciudades en las que vivían. Podemos recuperar las dos ciudades más grandes en las que vivían los amigos de una persona mediante una subconsulta CALL:

MATCH (person:Person)-[:knows]->(friend) CALL { WITH friend MATCH (friend)-[:lived_in]->(city) RETURN city ORDER BY city.population DESC LIMIT 2 } RETURN person, friend, city

En este ejemplo, la parte de la consulta dentro de CALL { ... } se ejecuta para cada friend que coincide con la cláusula MATCH anterior. Cuando se ejecuta la consulta interna, las cláusulas LIMIT y ORDER corresponden a las ciudades en las que vivía un amigo específico, por lo que obtenemos (como máximo) dos ciudades por amigo.

Todas las cláusulas de consulta están disponibles dentro de las subconsultas CALL. Esto también incluye las subconsultas CALL anidadas. Existen algunas restricciones para la primera cláusula WITH y las variables emitidas, que se explican a continuación.

Ámbito de las variables dentro de la subconsulta CALL

La cláusula WITH inicial debe importar las variables de las cláusulas anteriores a la subconsulta CALL que se utilizan dentro de ella. A diferencia de las cláusulas WITH normales, solo puede contener una lista de variables, pero no permite la creación de alias y no se puede usar junto con DISTINCT, ORDER BY, WHERE, SKIP o LIMIT.

Variables devueltas desde la subconsulta CALL

Las variables que se emiten desde la subconsulta CALL se especifican con la cláusula RETURN final. Tenga en cuenta que las variables emitidas no pueden superponerse con las variables anteriores a la subconsulta CALL.

Limitaciones

Por el momento, no se admiten actualizaciones dentro de una subconsulta CALL.

Funciones de openCypher en Neptune

Disponible en Neptune Database 1.4.1.0 y posteriores y en Neptune Analytics.

textIndexOf

textIndexOf(text :: STRING, lookup :: STRING, from = 0 :: INTEGER?, to = -1 :: INTEGER?) :: (INTEGER?)

Devuelve el índice de la primera aparición de lookup en el rango de text empezando por el desfase from (incluido) hasta el desfase to (excluido). Si to es -1, el rango continúa hasta el final de text. La indexación se basa en cero y se expresa en valores escalares Unicode (puntos de código no sustitutos).

RETURN textIndexOf('Amazon Neptune', 'e') { "results": [{ "textIndexOf('Amazon Neptune', 'e')": 8 }] }

collToSet

collToSet(values :: LIST OF ANY?) :: (LIST? OF ANY?)

Devuelve una nueva lista que contiene solo los elementos únicos de la lista original. Se mantiene el orden de la lista original (por ejemplo, [1, 6, 5, 1, 5] devuelve[1, 6, 5]).

RETURN collToSet([1, 6, 5, 1, 1, 5]) { "results": [{ "collToSet([1, 6, 5, 1, 1, 5])": [1, 6, 5] }] }

collSubtract

collSubtract(first :: LIST OF ANY?, second :: LIST OF ANY?) :: (LIST? OF ANY?)

Devuelve una nueva lista que contiene todos los elementos únicos de first, sin incluir los elementos de second.

RETURN collSubtract([2, 5, 1, 0], [1, 5]) { "results": [{ "collSubtract([2, 5, 1, 0], [1, 5])": [0, 2] }] }

collIntersection

collIntersection(first :: LIST? OF ANY?, second :: LIST? OF ANY?) :: (LIST? OF ANY?)

Devuelve una nueva lista que contiene todos los elementos únicos de la intersección de first y second.

RETURN collIntersection([2, 5, 1, 0], [1, 5]) { "results": [{ "collIntersection([2, 5, 1, 0], [1, 5])": [1, 5] }] }

Funciones de ordenación

Las siguientes secciones definen funciones para ordenar recopilaciones. Estas funciones utilizan argumentos de config mapa (en algunos casos opcionales) o una lista de varios mapas de este tipo, que definen la clave de clasificación y and/or la dirección de clasificación:

{ key: STRING, order: STRING }

En este caso, key es un mapa o una propiedad de nodo cuyo valor se utilizará para la ordenación. order es “asc” o “desc” (sin distinción entre mayúsculas y minúsculas) para especificar una ordenación ascendente o descendente, respectivamente. De forma predeterminada, la ordenación se realizará en orden ascendente.

collSort

collSort(coll :: LIST OF ANY, config :: MAP?) :: (LIST? OF ANY?)

Devuelve una nueva lista ordenada que contiene los elementos de la lista de entrada coll.

RETURN collSort([5, 3, 1], {order: 'asc'}) { "results": [{ "collSort([5, 3, 1])": [1, 3, 5] }] }

collSortMaps

collSortMaps(coll :: LIST OF MAP, config :: MAP) :: (LIST? OF ANY?)

Devuelve una lista de mapas ordenados por el valor de la propiedad key especificada.

RETURN collSortMaps([{name: 'Alice', age: 25}, {name: 'Bob', age: 35}, {name: 'Charlie', age: 18}], {key: 'age', order: 'desc'}) { "results": [{ "x": [{ "age": 35, "name": "Bob" }, { "age": 25, "name": "Alice" }, { "age": 18, "name": "Charlie" }] }] }

collSortMulti

collSortMulti(coll :: LIST OF MAP?, configs = [] :: LIST OF MAP, limit = -1 :: INTEGER?, skip = 0 :: INTEGER?) :: (LIST? OF ANY?)

Devuelve una lista de mapas ordenados por el valor de las propiedades key especificadas y, opcionalmente, aplica límites y omisiones.

RETURN collSortMulti([{name: 'Alice', age: 25}, {name: 'Bob', age: 35}, {name: 'Charlie', age: 18}], [{key: 'age', order: 'desc'}, {key:'name'}]) as x { "results": [{ "x": [{ "age": 35, "name": "Bob" }, { "age": 25, "name": "Alice" }, { "age": 18, "name": "Charlie" }] }] }

collSortNodes

collSortNodes(coll :: LIST OF NODE, config :: MAP) :: (LIST? OF NODE?)

Devuelve una versión ordenada de la lista de entrada coll, en la que los elementos del nodo se ordenan según los valores de sus respectivas propiedades key.

create (n:person {name: 'Alice', age: 23}), (m:person {name: 'Eve', age: 21}), (o:person {name:'Bob', age:25}) {"results":[]} match (n:person) with collect(n) as people return collSortNodes(people, {key: 'name', order: 'desc'}) { "results": [{ "collSortNodes(people, 'name')": [{ "~id": "e599240a-8c23-4337-8aa8-f603c8fb5488", "~entityType": "node", "~labels": ["person"], "~properties": { "age": 21, "name": "Eve" } }, { "~id": "8a6ef785-59e3-4a0b-a0ff-389655a9c4e6", "~entityType": "node", "~labels": ["person"], "~properties": { "age": 25, "name": "Bob" } }, { "~id": "466bc826-f47f-452c-8a27-6b7bdf7ae9b4", "~entityType": "node", "~labels": ["person"], "~properties": { "age": 23, "name": "Alice" } }] }] } match (n:person) with collect(n) as people return collSortNodes(people, {key: 'age'}) { "results": [{ "collSortNodes(people, '^age')": [{ "~id": "e599240a-8c23-4337-8aa8-f603c8fb5488", "~entityType": "node", "~labels": ["person"], "~properties": { "age": 21, "name": "Eve" } }, { "~id": "466bc826-f47f-452c-8a27-6b7bdf7ae9b4", "~entityType": "node", "~labels": ["person"], "~properties": { "age": 23, "name": "Alice" } }, { "~id": "8a6ef785-59e3-4a0b-a0ff-389655a9c4e6", "~entityType": "node", "~labels": ["person"], "~properties": { "age": 25, "name": "Bob" } }] }] }

Funciones temporales

Las funciones temporales están disponibles a partir de la versión 1.4.5.0 de Neptune.

day

day(temporal :: (datetime | date)) :: (LONG)

Devuelve el day del mes a partir de un valor de datetime o date. Para datetime: los valores se normalizan a UTC en función de la entrada antes de extraer el día. Para date: el día se extrae en función de la zona horaria.

La entrada datetime está disponible en Neptune Database y en Neptune Analytics:

RETURN day(datetime('2021-06-03T01:48:14Z')) { "results": [{ "day(datetime('2021-06-03T01:48:14Z'))": 3 }] }

En este caso, datetime se normaliza a UTC, por lo que, +08:00 se desplaza hacia atrás al 2 de junio.

RETURN day(datetime('2021-06-03T00:00:00+08:00')) { "results": [{ "day(datetime('2021-06-03T00:00:00+08:00'))": 2 }] }

La entrada date solo está disponible en Neptune Analytics:

RETURN day(date('2021-06-03Z')) { "results": [{ "day(date('2021-06-03Z'))": 3 }] }

date conserva la zona horaria y se mantiene el 3 de junio.

RETURN day(date('2021-06-03+08:00')) { "results": [{ "day(date('2021-06-03+08:00'))": 3 }] }

month

month(temporal :: (datetime | date)) :: (LONG)

Devuelve el mes a partir de un valor de datetime o date (1-12). Para datetime: los valores se normalizan a UTC en función de la entrada antes de extraer el mes. Para date: el mes se extrae en función de la zona horaria.

La entrada datetime está disponible en Neptune Database y en Neptune Analytics:

RETURN month(datetime('2021-06-03T01:48:14Z')) { "results": [{ "month(datetime('2021-06-03T01:48:14Z'))": 6 }] }

En este caso, datetime se normaliza a UTC, por lo que, +08:00 se desplaza hacia atrás al 31 de mayo.

RETURN month(datetime('2021-06-01T00:00:00+08:00')) { "results": [{ "month(datetime('2021-06-01T00:00:00+08:00'))": 5 }] }

La entrada date solo está disponible en Neptune Analytics:

RETURN month(date('2021-06-03Z')) { "results": [{ "month(date('2021-06-03Z'))": 6 }] }

date conserva la zona horaria y se mantiene el 1 de junio.

RETURN month(date('2021-06-01+08:00')) { "results": [{ "month(date('2021-06-01+08:00'))": 6 }] }

year

year(temporal :: (datetime | date)) :: (LONG)

Devuelve el año a partir de un valor de datetime o date. Para datetime: los valores se normalizan a UTC en función de la entrada antes de extraer el año. Para date: el año se extrae en función de la zona horaria.

La entrada datetime está disponible en Neptune Database y en Neptune Analytics:

RETURN year(datetime('2021-06-03T01:48:14Z')) { "results": [{ "year(datetime('2021-06-03T01:48:14Z'))": 2021 }] }

En este caso, datetime se normaliza a UTC, por lo que, +08:00 se desplaza hacia atrás al 31 de diciembre de 2020.

RETURN year(datetime('2021-01-01T00:00:00+08:00')) { "results": [{ "year(datetime('2021-01-01T00:00:00+08:00'))": 2020 }] }

La entrada date solo está disponible en Neptune Analytics:

RETURN year(date('2021-06-03Z')) { "results": [{ "year(date('2021-06-03Z'))": 2021 }] }

date conserva la zona horaria y se mantiene en junio de 2021.

RETURN year(date('2021-01-01+08:00')) { "results": [{ "year(date('2021-01-01+08:00'))": 2021 }] }

Funciones de openCypher en Neptune

Disponible en Neptune Database 1.4.6.0 y posteriores y en Neptune Analytics.

reduce()

Reduce procesa secuencialmente cada elemento de la lista combinándolo con un total acumulado o “acumulador”. Empezando por un valor inicial, actualiza el acumulador después de cada operación y utiliza ese valor actualizado en la siguiente iteración.

for i in (0, ..., n) acc = acc X list[I], where X denotes any binary operator

Una vez procesados todos los elementos, devuelve el resultado final acumulado.

Una estructura típica de reduce() sería: reduce(accumulator = initial , variable IN list | expression)

Especificaciones de tipo:

- initial: starting value for the accumulator :: (Long | FLOAT | STRING | LIST? OF (STRING, LONG, FLOAT)) - list: the input list :: LIST OF T where T matches initial type - variable :: represents each element in the input list - expression :: Only supports '+' and '*' operator - return :: Same type as initial

Restricciones:

Actualmente, la expresión reduce() solo admite:

  • Multiplicación numérica

  • Suma numérica

  • Concatenación de cadenas

  • Concatenación de listas

Se representan mediante el operador * o +. La expresión debe ser binaria, tal y como se especifica a continuación: expression pattern: accumulator + any variable or accumulator * any variable

Gestión del desbordamiento:

Neptune detecta los desbordamientos numéricos durante la evaluación de reduce() y responde de forma diferente según el tipo de datos:

LONG (signed 64‑bit) -------------------- • Valid range: –9 223 372 036 854 775 808 … 9 223 372 036 854 775 807 • If any intermediate or final value falls outside this range, Neptune aborts the query with long overflow error message. FLOAT (IEEE‑754 double) ----------------------- • Largest finite value ≈ 1.79 × 10^308 • Larger results overflow to INF Once `INF` is produced, it propagates through the remainder of the reduction.
Ejemplos:

Consulte los siguientes ejemplos de la función reduce().

1. Long Addition: RETURN reduce(sum = 0, n IN [1, 2, 3] | sum + n) { "results": [{ "reduce(sum = 0, n IN [1, 2, 3] | sum + n)": 6 }] } 2. String Concatenation: RETURN reduce(str = "", x IN ["A", "B", "C"] | str + x) { "results": [{ "reduce(str = "", x IN ["A", "B", "C"] | str + x)": "ABC" }] } 3. List Combination: RETURN reduce(lst = [], x IN [1, 2, 3] | lst + x) { "results": [{ "reduce(lst = [], x IN [1, 2, 3] | lst + x)": [1, 2, 3] }] } 4. Float Addition: RETURN reduce(total = 0.0, x IN [1.5, 2.5, 3.5] | total + x) { "results": [{ "reduce(total = 0.0, x IN [1.5, 2.5, 3.5] | total + x)": 7.5 }] } 5. Long Multiplication: RETURN reduce(product = 1, n IN [1, 2, 3] | product * n) { "results": [{ "reduce(product = 0, n IN [1, 2, 3] | product * n)": 6 }] } 6. Float Multiplication: RETURN reduce(product = 1.0, n IN [1.5, 2.5, 3.5] | product * n) { "results": [{ "reduce(product = 1.0, n IN [1.5, 2.5, 3.5] | product * n)": 13.125 }] } 7. Long Overflow (Exception): RETURN reduce(s = 9223372036854775807, x IN [2, 3] | s * x) AS result { "results": [{ "reduce(s = 9223372036854775807, x IN [2, 3] | s * x) AS result": long overflow }] } 8. Float Overflow: RETURN reduce(s = 9.0e307, x IN [8.0e307, 1.0e307] | s + x) AS result { "results": [{ "reduce(s = 9.0e307, x IN [8.0e307, 1.0e307] | s + x) AS result": INF }] }