

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Riscrittura delle query Cypher da eseguire in openCypher su Neptune
<a name="migration-opencypher-rewrites"></a>

openCypher è un linguaggio di query dichiarativo per grafi di proprietà che è stato sviluppato originariamente da Neo4j, per poi diventare open source nel 2015, e che ha contribuito al [progetto openCypher](https://www.opencypher.org/) con una licenza open source Apache 2. Noi crediamo che l'open source sia un bene per tutti e ci impegniamo a portare il valore dell'open source ai nostri clienti e l'eccellenza operativa delle AWS comunità open source. AWS

OpenCypher la sintassi è documentata nel [Cypher Query Language Reference](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf), versione 9.

Poiché openCypher contiene un sottoinsieme della sintassi e delle caratteristiche del linguaggio di query Cypher, alcuni scenari di migrazione richiedono la riscrittura delle query in moduli compatibili con openCypher oppure la valutazione di metodi alternativi per ottenere la funzionalità desiderata.

Questa sezione contiene alcuni consigli non esaustivi per gestire le differenze più comuni. È necessario testare accuratamente qualsiasi applicazione utilizzando queste riscritture per assicurarsi che i risultati siano quelli previsti.

## Riscrittura delle funzioni di predicato `None`, `All` e `Any`
<a name="migration-opencypher-rewrites-none-all-any"></a>

Queste funzioni non fanno parte della specifica openCypher. È possibile ottenere risultati simili in openCypher utilizzando la comprensione di lista.

Ad esempio, trova tutti i percorsi che vanno dal nodo `Start` al nodo `End`, ma nessun percorso può attraversare un nodo con una proprietà di classe `D`:

```
# Neo4J Cypher code
match p=(a:Start)-[:HOP*1..]->(z:End)
where none(node IN nodes(p) where node.class ='D')
return p

# Neptune openCypher code
match p=(a:Start)-[:HOP*1..]->(z:End)
where size([node IN nodes(p) where node.class = 'D']) = 0
return p
```

La comprensione di lista consente di ottenere questi risultati come descritto di seguito:

```
all  => size(list_comprehension(list)) = size(list)
any  => size(list_comprehension(list)) >= 1
none => size(list_comprehension(list)) = 0
```

## Riscrittura della funzione Cypher `reduce()` in openCypher
<a name="migration-opencypher-rewrites-reduce"></a>

La funzione `reduce()` non fa parte delle specifiche openCypher. Viene spesso utilizzata per creare un'aggregazione di dati a partire da elementi all'interno di un elenco. In molti casi, è possibile utilizzare una combinazione di comprensione di lista e della clausola `UNWIND` per ottenere risultati simili.

Ad esempio, la seguente query Cypher trova tutti gli aeroporti su rotte che comprendono da uno a tre scali Anchorage (ANC) e Austin (AUS) e restituisce la distanza totale di ciascun percorso:

```
MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'})
RETURN p, reduce(totalDist=0, r in relationships(p) | totalDist + r.dist) AS totalDist
ORDER BY totalDist LIMIT 5
```

Puoi scrivere la stessa query in openCypher per Neptune come segue:

```
MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'})
UNWIND [i in relationships(p) | i.dist] AS di
RETURN p, sum(di) AS totalDist
ORDER BY totalDist
LIMIT 5
```

## Riscrittura della clausola Cypher FOREACH in openCypher
<a name="migration-opencypher-rewrites-foreach"></a>

La clausola FOREACH non fa parte delle specifiche openCypher. Viene spesso utilizzata per aggiornare i dati in mezzo a una query, spesso da aggregazioni o elementi all'interno di un percorso.

Come esempio di percorso, trova tutti gli aeroporti su una rotta con non più di due scali tra Anchorage (ANC) e Austin (AUS) e imposta la proprietà Visited per ciascuno di essi:

```
# Neo4J Example
MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'})
FOREACH (n IN nodes(p) | SET n.visited = true)

# Neptune openCypher
MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'})
WITH nodes(p) as airports
UNWIND airports as a
SET a.visited=true
```

Un altro esempio è:

```
# Neo4J Example
MATCH p=(start)-[*]->(finish)
WHERE start.name = 'A' AND finish.name = 'D'
FOREACH (n IN nodes(p) | SET n.marked = true)

# Neptune openCypher
MATCH p=(start)-[*]->(finish)
WHERE start.name = 'A' AND finish.name = 'D'
UNWIND nodes(p) AS n
SET n.marked = true
```

## Riscrittura delle procedure APOC Neo4j in Neptune
<a name="migration-opencypher-rewrites-apoc"></a>

Gli esempi seguenti utilizzano openCypher per sostituire alcune delle [procedure APOC](https://neo4j.com/blog/intro-user-defined-procedures-apoc/) usate più comunemente. Questi esempi sono solo di riferimento e hanno lo scopo di fornire alcuni suggerimenti su come gestire scenari comuni. In pratica, ogni applicazione è diversa ed è necessario trovare strategie personalizzate per fornire tutte le funzionalità di cui hai bisogno.

### Riscrittura delle procedure `apoc.export`
<a name="migration-opencypher-rewrites-apoc-export"></a>

Neptune offre un array di opzioni sia per le esportazioni a grafo completo che per quelle basate su query in vari formati di output come CSV e JSON, il tutto mediante l'utilità [neptune-export](https://github.com/aws/neptune-export) (vedi [Esportazione di dati da un cluster database Neptune](neptune-data-export.md)).

### Riscrittura delle procedure `apoc.schema`
<a name="migration-opencypher-rewrites-apoc-schema"></a>

Neptune non ha schemi, indici o vincoli definiti in modo esplicito, perciò molte procedure `apoc.schema` non sono più necessarie. Alcuni esempi sono:
+ `apoc.schema.assert`
+ `apoc.schema.node.constraintExists`
+ `apoc.schema.node.indexExists`,
+ `apoc.schema.relationship.constraintExists`
+ `apoc.schema.relationship.indexExists`
+ `apoc.schema.nodes`
+ `apoc.schema.relationships`

openCypher per Neptune supporta il recupero di valori simili a quelli utilizzati dalle procedure, come mostrato di seguito, ma potrebbe riscontrare problemi di prestazioni su grafi più grandi poiché sarebbe necessario scansionare un'ampia porzione del grafo per restituire la risposta.

```
# openCypher replacement for apoc.schema.properties.distinct
MATCH (n:airport)
RETURN DISTINCT n.runways
```

```
# openCypher replacement for apoc.schema.properties.distinctCount
MATCH (n:airport)
RETURN DISTINCT n.runways, count(n.runways)
```

### Alternative alle procedure `apoc.do`
<a name="migration-opencypher-rewrites-apoc-do"></a>

Queste procedure vengono utilizzate per consentire l'esecuzione di query condizionali facili da implementare utilizzando altre clausole openCypher. In Neptune ci sono almeno due modi per ottenere un comportamento simile:
+ Un modo è combinare le funzionalità della comprensione di lista di openCypher con la clausola `UNWIND`.
+ Un altro modo è usare i passaggi choose() e coalesce() in Gremlin.

Di seguito sono riportati alcuni esempi di questi approcci.

#### Alternative ad apoc.do.when
<a name="migration-opencypher-rewrites-apoc-do-when"></a>

```
# Neo4J Example
MATCH (n:airport {region: 'US-AK'})
CALL apoc.do.when(
 n.runways>=3,
 'SET n.is_large_airport=true RETURN n',
 'SET n.is_large_airport=false RETURN n',
 {n:n}
) YIELD value
WITH collect(value.n) as airports
RETURN size([a in airports where a.is_large_airport]) as large_airport_count,
size([a in airports where NOT a.is_large_airport]) as small_airport_count


# Neptune openCypher
MATCH (n:airport {region: 'US-AK'})
WITH n.region as region, collect(n) as airports
WITH [a IN airports where a.runways >= 3] as large_airports,
[a IN airports where a.runways < 3] as small_airports, airports
UNWIND large_airports as la
SET la.is_large_airport=true
WITH DISTINCT small_airports, airports
UNWIND small_airports as la
    SET la.small_airports=true
WITH DISTINCT airports
RETURN size([a in airports where a.is_large_airport]) as large_airport_count,
size([a in airports where NOT a.is_large_airport]) as small_airport_count

#Neptune Gremlin using choose()
g.V().
  has('airport', 'region', 'US-AK').
  choose(
    values('runways').is(lt(3)),
    property(single, 'is_large_airport', false),
    property(single, 'is_large_airport', true)).
  fold().
  project('large_airport_count', 'small_airport_count').
    by(unfold().has('is_large_airport', true).count()).
    by(unfold().has('is_large_airport', false).count())

 #Neptune Gremlin using coalesce() 
g.V().
  has('airport', 'region', 'US-AK').
  coalesce(
    where(values('runways').is(lt(3))).
    property(single, 'is_large_airport', false),
    property(single, 'is_large_airport', true)).
  fold().
  project('large_airport_count', 'small_airport_count').
    by(unfold().has('is_large_airport', true).count()).
    by(unfold().has('is_large_airport', false).count())
```

#### Alternative ad apoc.do.case
<a name="migration-opencypher-rewrites-apoc-do-case"></a>

```
# Neo4J Example
MATCH (n:airport {region: 'US-AK'})
CALL apoc.case([
 n.runways=1, 'RETURN "Has one runway" as b',
 n.runways=2, 'RETURN "Has two runways" as b'
 ],
 'RETURN "Has more than 2 runways" as b'
) YIELD value 
RETURN {type: value.b,airport: n}

# Neptune openCypher
MATCH (n:airport {region: 'US-AK'})
WITH n.region as region, collect(n) as airports
WITH [a IN airports where a.runways =1] as single_runway,
[a IN airports where a.runways =2] as double_runway,
[a IN airports where a.runways >2] as many_runway
UNWIND single_runway as sr
    WITH {type: "Has one runway",airport: sr} as res, double_runway, many_runway
WITH DISTINCT double_runway as double_runway, collect(res) as res, many_runway
UNWIND double_runway as dr
    WITH {type: "Has two runways",airport: dr} as two_runways, res, many_runway
WITH collect(two_runways)+res as res, many_runway
UNWIND many_runway as mr
    WITH {type: "Has more than 2 runways",airport: mr} as res2, res, many_runway
WITH collect(res2)+res as res
UNWIND res as r
RETURN r

#Neptune Gremlin using choose()
g.V().
  has('airport', 'region', 'US-AK').
  project('type', 'airport').
    by(
      choose(values('runways')).
        option(1, constant("Has one runway")).
        option(2, constant("Has two runways")).
        option(none, constant("Has more than 2 runways"))).
    by(elementMap())

 #Neptune Gremlin using coalesce()
 g.V().
  has('airport', 'region', 'US-AK').
  project('type', 'airport').
    by(
      coalesce(
        has('runways', 1).constant("Has one runway"),
        has('runways', 2).constant("Has two runways"),
        constant("Has more than 2 runways"))).
    by(elementMap())
```

## Alternative alle proprietà basate su elenco
<a name="migration-opencypher-rewrites-lists"></a>

Neptune attualmente non supporta la memorizzazione di proprietà basate su elenco. Tuttavia, è possibile ottenere risultati simili memorizzando i valori dell'elenco come stringa separata da virgole e, successivamente, utilizzando le funzioni `join()` e `split()` per costruire e decostruire la proprietà di elenco.

Ad esempio, per salvare un elenco di tag come proprietà, potremmo usare l'esempio di riscrittura che mostra come recuperare una proprietà separata da virgole, quindi utilizzare le funzioni `split()` e `join()` con la comprensione di lista per ottenere risultati simili:

```
# Neo4j Example (In this example, tags is a durable list of string.
MATCH (person:person {name: "TeeMan"})
WITH person, [tag in person.tags WHERE NOT (tag IN ['test1', 'test2', 'test3'])] AS newTags
SET person.tags = newTags
RETURN person

# Neptune openCypher 
MATCH (person:person {name: "TeeMan"})
WITH person, [tag in split(person.tags, ',') WHERE NOT (tag IN ['test1', 'test2', 'test3'])] AS newTags
SET person.tags = join(newTags,',')
RETURN person
```

## Riscrittura delle sottoquery CALL
<a name="migration-opencypher-rewrites-call-subqueries"></a>

 Le sottoquery `CALL` Neptune non supportano la `CALL (friend) { ... }` sintassi per l'importazione di variabili nell'ambito della sottoquery (in questo esempio). `friend` Si prega di utilizzare la `WITH` clausola all'interno della sottoquery per lo stesso scopo, ad esempio. `CALL { WITH friend ... }` 

 Le `CALL` sottoquery opzionali non sono supportate in questo momento. 

## Altre differenze tra Neptune openCypher e Cypher
<a name="opencypher-compliance-other-differences"></a>
+ Neptune supporta solo connessioni TCP per il protocollo Bolt. WebSocketsle connessioni per Bolt non sono supportate.
+ Neptune openCypher rimuove gli spazi bianchi come definito da Unicode nelle funzioni `trim()`, `ltrim()` e `rtrim()`.
+ In Neptune openCypher, `tostring(`double`)` non passa automaticamente alla notazione E per valori grandi di double.