

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à.

# Esempi di semantica delle transazioni Neptune
<a name="transactions-examples"></a>

I seguenti esempi illustrano diversi casi d'uso per la semantica delle transazioni in Amazon Neptune.

**Topics**
+ [Inserimento condizionale di una proprietà](#transactions-examples-conditional-insertion)
+ [Unicità del valore della proprietà](#transactions-examples-unique-property)
+ [Modifica della proprietà condizionale](#transactions-examples-conditional-edit)
+ [Sostituzione di una proprietà](#transactions-examples-replace)
+ [Evitare elementi pendenti](#transactions-examples-dangling)

## Esempio 1: Inserimento di una proprietà solo se non esiste
<a name="transactions-examples-conditional-insertion"></a>

Supponi di volerti assicurare che una proprietà sia impostata solo una volta. Ad esempio, supponi che più query stiano tentando di assegnare a una persona un punteggio di credito simultaneamente. Desideri che venga inserita una sola un'istanza della proprietà e che le altre query non vadano a buon fine perché la proprietà è già stata impostata.

```
# GREMLIN:
g.V('person1').hasLabel('Person').coalesce(has('creditScore'), property('creditScore', 'AAA+'))

# SPARQL:
INSERT { :person1 :creditScore "AAA+" .}
WHERE  { :person1 rdf:type :Person .
         FILTER NOT EXISTS { :person1 :creditScore ?o .} }
```

La fase `property()` di Gremlin inserisce una proprietà con la chiave e il valore forniti. La fase `coalesce()` esegue il primo argomento nella prima fase e se non va a buon fine, esegue la seconda fase:

Prima di inserire il valore per la proprietà `creditScore` per un determinato vertice `person1`, una transazione deve cercare di leggere il valore `creditScore` possibilmente inesistente per `person1`. Questa lettura tentata blocca l'intervallo `SP` per `S=person1` e `P=creditScore` nell'indice `SPOG` in cui il valore `creditScore` esiste o verrà scritto.

L'uso di questo blocco di intervallo impedisce a qualsiasi transazione simultanea di inserire un valore `creditScore` simultaneamente. Quando sono presenti più transazioni parallele, solo una alla volta può aggiornare il valore. Ciò esclude l'anomalia di creazione di più proprietà `creditScore`.

## Esempio 2: Affermare che il valore di una proprietà è univoco a livello globale
<a name="transactions-examples-unique-property"></a>

Supponi di voler inserire una persona con un numero di previdenza sociale come una chiave primaria. Desideri che la query di mutazione garantisca che, a livello globale, nessun altro nel database abbia lo stesso numero di previdenza sociale:

```
# GREMLIN:
g.V().has('ssn', 123456789).fold()
  .coalesce(__.unfold(),
            __.addV('Person').property('name', 'John Doe').property('ssn', 123456789'))

# SPARQL:
INSERT { :person1 rdf:type :Person .
         :person1 :name "John Doe" .
         :person1 :ssn 123456789 .}
WHERE  { FILTER NOT EXISTS { ?person :ssn 123456789 } }
```

Questo esempio è simile a quello precedente. La differenza principale è che il blocco dell'intervallo viene eseguito sull'indice `POGS` anziché sull'indice `SPOG`.

La transazione che esegue la query deve leggere il modello, `?person :ssn 123456789`, in cui le posizioni `P` e `O` sono vincolate. Il blocco dell'intervallo viene eseguito sull'indice `POGS` per `P=ssn` e `O=123456789`.
+ Se il modello esiste, non viene eseguita alcuna operazione.
+ In caso contrario, il blocco impedisce a qualsiasi transazione simultanea di inserire anche tale numero di previdenza sociale

## Esempio 3: Modifica di una proprietà se un'altra proprietà ha un valore specificato
<a name="transactions-examples-conditional-edit"></a>

Supponi che vari eventi in un gioco spostino una persona dal livello 1 al livello 2 e che venga loro assegnata una nuova proprietà `level2Score` impostata su zero. Occorre accertarsi che più istanze simultanee di tale transazione non siano in grado di creare più istanze della proprietà score a livello due. Le query in Gremlin e SPARQL potrebbero essere simili alle seguenti.

```
# GREMLIN:
g.V('person1').hasLabel('Person').has('level', 1)
 .property('level2Score', 0)
 .property(Cardinality.single, 'level', 2)

# SPARQL:
DELETE { :person1 :level 1 .}
INSERT { :person1 :level2Score 0 .
         :person1 :level 2 .}
WHERE  { :person1 rdf:type :Person .
         :person1 :level 1 .}
```

In Gremlin, quando si specifica `Cardinality.single`, la fase `property()` aggiunge una nuova proprietà o sostituisce un valore di proprietà esistente con il nuovo valore specificato.

Qualsiasi aggiornamento a un valore di proprietà, ad esempio incrementando `level` da 1 a 2, viene implementato come un'eliminazione del record corrente e l'inserimento di un nuovo record con il nuovo valore di proprietà. In questo caso, il record con il numero di livello 1 viene eliminato e un record con il numero di livello 2 viene reinserito.

Affinché la transazione sia in grado di aggiungere `level2Score` e aggiornare `level` da 1 a 2, è necessario innanzitutto verificare che il valore `level` sia attualmente pari a 1. In questo modo, esegue un blocco dell'intervallo sul prefisso `SPO` per `S=person1`, `P=level` e `O=1` nell'indice `SPOG`. Questo blocco impedisce alle transazioni simultanee di eliminare la tripla versione 1 e, di conseguenza, non possono verificarsi aggiornamenti simultanei in conflitto.

## Esempio 4: Sostituzione di una proprietà esistente
<a name="transactions-examples-replace"></a>

Alcuni eventi potrebbero aggiornare il punteggio di credito di una persona a un nuovo valore (qui `BBB`). Tuttavia, vuoi essere certo che gli eventi simultanei di tale tipo non possano creare più proprietà del punteggio di credito per una persona.

```
# GREMLIN:
g.V('person1').hasLabel('Person')
 .sideEffect(properties('creditScore').drop())
 .property('creditScore', 'BBB')

# SPARQL:
DELETE { :person1 :creditScore ?o .}
INSERT { :person1 :creditScore "BBB" .}
WHERE  { :person1 rdf:type :Person .
         :person1 :creditScore ?o .}
```

Questo caso è simile all'esempio 3, tranne per il fatto che anziché bloccare il prefisso `SPO`, Neptune blocca il prefisso `SP` solo con `S=person1` e `P=creditScore`. Questo impedisce alle transazioni simultanee di inserire o eliminare triple con la proprietà `creditScore` per il soggetto `person1`.

## Esempio 5: Evitare proprietà o archi pendenti
<a name="transactions-examples-dangling"></a>

L'aggiornamento di un'entità non deve lasciare un elemento pendente, ovvero una proprietà o edge associata a un'entità per cui non è definito un tipo. Questo è un problema solo in SPARQL, perché Gremlin ha vincoli integrati per evitare elementi pendenti.

```
# SPARQL:
tx1: INSERT { :person1 :age 23 } WHERE { :person1 rdf:type :Person }
tx2: DELETE { :person1 ?p ?o }
```

La query `INSERT` deve leggere e bloccare il prefisso `SPO` con `S=person1`, `P=rdf:type` e `O=Person` nell'indice `SPOG`. Il blocco impedisce che la query `DELETE` vada a buon fine in parallelo.

Nel conflitto tra la query `DELETE` che cerca di eliminare il record `:person1 rdf:type :Person` e la query `INSERT` che legge il record e crea un blocco dell'intervallo sul suo `SPO` nell'indice `SPOG`, sono possibili i seguenti risultati:
+ Se la query `INSERT` esegue il commit prima che la query `DELETE` legga ed elimini tutti i record per `:person1`, `:person1` viene rimosso completamente dal database, incluso il nuovo record inserito.
+ Se la query `DELETE` esegue il commit prima che la query `INSERT` cerchi di leggere il record `:person1 rdf:type :Person`, la lettura osserva la modifica sottoposta a commit. Ovvero, non trova alcun record `:person1 rdf:type :Person` e quindi diventa un no-op.
+ Se la query `INSERT` legge prima che lo faccia la query `DELETE`, la tripla `:person1 rdf:type :Person` viene bloccata e la query `DELETE` viene bloccata fino al commit della query INSERT, come nel primo caso in precedenza.
+ Se `DELETE` legge prima della query `INSERT` e la query `INSERT` cerca di leggere e di eseguire un blocco sul prefisso `SPO` per il record, viene rilevato un conflitto. Questo perché la tripla è stata contrassegnata per la rimozione e `INSERT` non va a buon fine.

In tutte queste possibili sequenze di eventi, non viene creato alcun edge pendente.