

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
<a name="access-graph-opencypher-extensions"></a>

 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](feature-opencypher-compliance.md) 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. 

## Acceso a datos de S3 en tiempo de consulta
<a name="opencypher-compliance-neptune-read"></a>

Disponible en Neptune Database 1.4.7.0 y versiones posteriores.

Neptune admite la `neptune.read()` función de leer datos CSV o Parquet de Amazon S3 directamente en las consultas de OpenCypher. A diferencia del cargador masivo, que importa los datos antes de realizar las consultas, `neptune.read()` accede a los datos de Amazon S3 en el momento de la ejecución de la consulta.

Para obtener la documentación completa, consulte. [neptune.read ()](access-graph-opencypher-21-extensions-s3-read.md)

## La función `join()` específica de Neptune
<a name="opencypher-compliance-join-function"></a>

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
<a name="opencypher-compliance-removeKeyFromMap-function"></a>

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
<a name="opencypher-compliance-custom-ids"></a>

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](engine-releases-1.2.0.2.md), 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](#opencypher-compliance-custom-ids-migrating).

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
<a name="opencypher-compliance-custom-ids-migrating"></a>

Con la [versión 1.2.0.2 del motor](engine-releases-1.2.0.2.md), 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 '\$1id' en la propiedad 'newId'
+ y elimina la propiedad '\$1id' 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
<a name="call-subquery-support"></a>

 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
<a name="variable-scope-inside-call-subquery"></a>

 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
<a name="variables-returned-call-subquery"></a>

 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
<a name="call-subquery-limitations"></a>

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

## Funciones de openCypher en Neptune
<a name="opencypher-compliance-new-functions"></a>

 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
<a name="sorting-functions"></a>

 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
<a name="temporal-functions"></a>

 Las funciones temporales están disponibles a partir de la versión [1.4.5.0](https://docs.aws.amazon.com/releases/release-1.4.5.0.xml) de Neptune. 

### day
<a name="temporal-functions-day"></a>

 `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, \$108: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
<a name="temporal-functions-month"></a>

 `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, \$108: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
<a name="temporal-functions-year"></a>

 `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, \$108: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
<a name="openCypher-functions"></a>

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

#### reduce()
<a name="openCypher-functions-reduce"></a>

 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
    }]
}
```