Transazioni Cloud Datastore

Una transazione è un insieme di operazioni di Datastore su una o più entità in un massimo di 25 gruppi di entità. Ogni transazione è garantita come atomica, il che significa che le transazioni non vengono mai applicate parzialmente. Vengono applicate tutte le operazioni nella transazione o nessuna.

Utilizzo delle transazioni

Le transazioni hanno una durata massima di 270 secondi con un periodo di scadenza di inattività di 10 secondi dopo 30 secondi.

Un'operazione potrebbe non riuscire quando:

  • Sono state tentate troppe modifiche simultanee nello stesso gruppo di entità.
  • La transazione supera un limite di risorse.
  • Datastore rileva un errore interno.

In tutti questi casi, l'API Datastore restituisce un errore.

Le transazioni sono una funzionalità facoltativa di Datastore; non è necessario utilizzarle per eseguire operazioni di Datastore.

Un'applicazione può eseguire un insieme di istruzioni e operazioni Datastore in un'unica transazione, in modo che se un'istruzione o un'operazione genera un'eccezione, nessuna delle operazioni Datastore nel set viene applicata. L'applicazione definisce le azioni da eseguire nella transazione.

Lo snippet seguente mostra come eseguire una transazione utilizzando l'API Datastore. Trasferisce denaro da un conto all'altro.

C#

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore C#.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

private void TransferFunds(Key fromKey, Key toKey, long amount)
{
    using (var transaction = _db.BeginTransaction())
    {
        var entities = transaction.Lookup(fromKey, toKey);
        entities[0]["balance"].IntegerValue -= amount;
        entities[1]["balance"].IntegerValue += amount;
        transaction.Update(entities);
        transaction.Commit();
    }
}

Go

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Go.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

type BankAccount struct {
	Balance int
}

const amount = 50
keys := []*datastore.Key{to, from}
tx, err := client.NewTransaction(ctx)
if err != nil {
	log.Fatalf("client.NewTransaction: %v", err)
}
accs := make([]BankAccount, 2)
if err := tx.GetMulti(keys, accs); err != nil {
	tx.Rollback()
	log.Fatalf("tx.GetMulti: %v", err)
}
accs[0].Balance += amount
accs[1].Balance -= amount
if _, err := tx.PutMulti(keys, accs); err != nil {
	tx.Rollback()
	log.Fatalf("tx.PutMulti: %v", err)
}
if _, err = tx.Commit(); err != nil {
	log.Fatalf("tx.Commit: %v", err)
}

Java

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Java.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

void transferFunds(Key fromKey, Key toKey, long amount) {
  Transaction txn = datastore.newTransaction();
  try {
    List<Entity> entities = txn.fetch(fromKey, toKey);
    Entity from = entities.get(0);
    Entity updatedFrom =
        Entity.newBuilder(from).set("balance", from.getLong("balance") - amount).build();
    Entity to = entities.get(1);
    Entity updatedTo =
        Entity.newBuilder(to).set("balance", to.getLong("balance") + amount).build();
    txn.put(updatedFrom, updatedTo);
    txn.commit();
  } finally {
    if (txn.isActive()) {
      txn.rollback();
    }
  }
}

Node.js

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Node.js.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

async function transferFunds(fromKey, toKey, amount) {
  const transaction = datastore.transaction();
  await transaction.run();
  const results = await Promise.all([
    transaction.get(fromKey),
    transaction.get(toKey),
  ]);
  const accounts = results.map(result => result[0]);

  accounts[0].balance -= amount;
  accounts[1].balance += amount;

  transaction.save([
    {
      key: fromKey,
      data: accounts[0],
    },
    {
      key: toKey,
      data: accounts[1],
    },
  ]);

  return await transaction.commit();
}

PHP

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore PHP.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

/**
 * Update two entities in a transaction.
 *
 * @param string $fromKeyId
 * @param string $toKeyId
 * @param int $amount
 * @param string $namespaceId
 */
function transfer_funds(
    string $fromKeyId,
    string $toKeyId,
    int $amount,
    string $namespaceId = null
) {
    $datastore = new DatastoreClient(['namespaceId' => $namespaceId]);
    $transaction = $datastore->transaction();
    $fromKey = $datastore->key('Account', $fromKeyId);
    $toKey = $datastore->key('Account', $toKeyId);
    // The option 'sort' is important here, otherwise the order of the result
    // might be different from the order of the keys.
    $result = $transaction->lookupBatch([$fromKey, $toKey], ['sort' => true]);
    if (count($result['found']) != 2) {
        $transaction->rollback();
    }
    $fromAccount = $result['found'][0];
    $toAccount = $result['found'][1];
    $fromAccount['balance'] -= $amount;
    $toAccount['balance'] += $amount;
    $transaction->updateBatch([$fromAccount, $toAccount]);
    $transaction->commit();
}

Python

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Python.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

def transfer_funds(client, from_key, to_key, amount):
    with client.transaction():
        from_account = client.get(from_key)
        to_account = client.get(to_key)

        from_account["balance"] -= amount
        to_account["balance"] += amount

        client.put_multi([from_account, to_account])

Ruby

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Ruby.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

def transfer_funds from_key, to_key, amount
  datastore.transaction do |tx|
    from = tx.find from_key
    from["balance"] -= amount
    to = tx.find to_key
    to["balance"] += amount
    tx.save from, to
  end
end

Tieni presente che, per mantenere i nostri esempi più concisi, a volte omettiamo rollback se la transazione non va a buon fine. Nel codice di produzione è importante assicurarsi che ogni transazione venga eseguita esplicitamente o venga eseguito il rollback.

Cosa si può fare in una transazione

Tutte le operazioni di Datastore in una transazione possono essere eseguite su un massimo di venticinque gruppi di entità. Sono incluse le query per le entità in base all'antenato, il recupero delle entità in base alla chiave, l'aggiornamento delle entità e l'eliminazione delle entità.

Quando due o più transazioni tentano contemporaneamente di modificare entità in uno o più gruppi di entità comuni, solo la prima transazione che esegue il commit delle modifiche può avere esito positivo; tutte le altre non andranno a buon fine al momento del commit. A causa di questo design, l'utilizzo dei gruppi di entità limita il numero di scritture simultanee che puoi eseguire su qualsiasi entità dei gruppi. Quando inizia una transazione, Datastore utilizza il controllo della concorrenza ottimistico controllando l'ora dell'ultimo aggiornamento dei gruppi di entità utilizzati nella transazione. Al momento dell'commit di una transazione per i gruppi di entità, Datastore controlla di nuovo l'ora dell'ultimo aggiornamento dei gruppi di entità utilizzati nella transazione. Se è cambiato dal nostro controllo iniziale, viene restituito un errore. Per una spiegazione dei gruppi di entità, vedi Percorsi degli antenati.

Isolamento e coerenza

Al di fuori delle transazioni, il livello di isolamento di Datastore è più simile a read committed. All'interno delle transazioni viene applicato l'isolamento serializzabile. Ciò significa che un'altra transazione non può modificare contemporaneamente i dati letti o modificati da questa transazione. Per ulteriori informazioni sui livelli di isolamento, consulta la pagina wiki sull'isolamento serializzabile e l'articolo sull'isolamento delle transazioni.

In una transazione, tutte le letture riflettono lo stato corrente e coerente di Datastore al momento dell'avvio della transazione. Le query e le ricerche all'interno di una transazione hanno la garanzia di vedere un singolo snapshot coerente di Datastore dall'inizio della transazione. Le entità e le righe dell'indice nei gruppi di entità della transazione vengono aggiornate completamente in modo che le query restituiscano l'insieme completo e corretto di entità di risultato, senza i falsi positivi o i falsi negativi descritti in Isolamento delle transazioni che possono verificarsi nelle query al di fuori delle transazioni.

Questa vista istantanea coerente si estende anche alle letture dopo le scritture all'interno delle transazioni. A differenza della maggior parte dei database, le query e i get all'interno di una transazione Datastore non vedono i risultati delle scritture precedenti all'interno della transazione. Nello specifico, se un'entità viene modificata o eliminata all'interno di una transazione, una query o una ricerca restituisce la versione originale dell'entità dall'inizio della transazione, oppure non restituisce nulla se l'entità non esisteva in quel momento.

Utilizzi per le transazioni

Un utilizzo delle transazioni è l'aggiornamento di un'entità con un nuovo valore della proprietà rispetto al suo valore corrente. L'esempio transferFunds riportato sopra lo fa per due entità, prelevando denaro da un account e trasferendolo in un altro. L'API Datastore non riprova automaticamente le transazioni, ma puoi aggiungere la tua logica per riprovarle, ad esempio per gestire i conflitti quando un'altra richiesta aggiorna la stessa entità contemporaneamente.

C#

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore C#.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

/// <summary>
/// Retry the action when a Grpc.Core.RpcException is thrown.
/// </summary>
private T RetryRpc<T>(Func<T> action)
{
    List<Grpc.Core.RpcException> exceptions = null;
    var delayMs = _retryDelayMs;
    for (int tryCount = 0; tryCount < _retryCount; ++tryCount)
    {
        try
        {
            return action();
        }
        catch (Grpc.Core.RpcException e)
        {
            if (exceptions == null)
                exceptions = new List<Grpc.Core.RpcException>();
            exceptions.Add(e);
        }
        System.Threading.Thread.Sleep(delayMs);
        delayMs *= 2;  // Exponential back-off.
    }
    throw new AggregateException(exceptions);
}

private void RetryRpc(Action action)
{
    RetryRpc(() => { action(); return 0; });
}

[Fact]
public void TestTransactionalRetry()
{
    int tryCount = 0;
    var keys = UpsertBalances();
    RetryRpc(() =>
    {
        using (var transaction = _db.BeginTransaction())
        {
            TransferFunds(keys[0], keys[1], 10, transaction);
            // Insert a conflicting transaction on the first try.
            if (tryCount++ == 0)
                TransferFunds(keys[1], keys[0], 5);
            transaction.Commit();
        }
    });
    Assert.Equal(2, tryCount);
}

Go

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Go.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

type BankAccount struct {
	Balance int
}

const amount = 50
_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
	keys := []*datastore.Key{to, from}
	accs := make([]BankAccount, 2)
	if err := tx.GetMulti(keys, accs); err != nil {
		return err
	}
	accs[0].Balance += amount
	accs[1].Balance -= amount
	_, err := tx.PutMulti(keys, accs)
	return err
})

Java

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Java.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

int retries = 5;
while (true) {
  try {
    transferFunds(fromKey, toKey, 10);
    break;
  } catch (DatastoreException e) {
    if (retries == 0) {
      throw e;
    }
    --retries;
  }
}
// Retry handling can also be configured and automatically applied using google-cloud-java.

Node.js

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Node.js.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

async function transferFundsWithRetry() {
  const maxTries = 5;

  async function tryRequest(currentAttempt, delay) {
    try {
      await transferFunds(fromKey, toKey, 10);
    } catch (err) {
      if (currentAttempt <= maxTries) {
        // Use exponential backoff
        setTimeout(async () => {
          await tryRequest(currentAttempt + 1, delay * 2);
        }, delay);
      }
      throw err;
    }
  }

  await tryRequest(1, 100);
}

PHP

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore PHP.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

$retries = 5;
for ($i = 0; $i < $retries; $i++) {
    try {
        require_once __DIR__ . '/transfer_funds.php';
        transfer_funds($fromKeyId, $toKeyId, 10, $namespaceId);
    } catch (\Google\Cloud\Core\Exception\ConflictException $e) {
        // if $i >= $retries, the failure is final
        continue;
    }
    // Succeeded!
    break;
}

Python

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Python.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

import google.cloud.exceptions

for _ in range(5):
    try:
        transfer_funds(client, account1.key, account2.key, 50)
        break
    except google.cloud.exceptions.Conflict:
        continue
else:
    print("Transaction failed.")

Ruby

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Ruby.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

(1..5).each do |i|
  begin
    return transfer_funds from_key, to_key, amount
  rescue Google::Cloud::Error => e
    raise e if i == 5
  end
end

Ciò richiede una transazione perché il valore di balance in un'entità può essere aggiornato da un altro utente dopo che questo codice ha recuperato l'oggetto, ma prima di salvarlo. Senza una transazione, la richiesta dell'utente utilizza il valore di balance precedente all'aggiornamento dell'altro utente e il salvataggio sovrascrive il nuovo valore. Con una transazione, l'applicazione viene informata dell'aggiornamento dell'altro utente.

Un altro uso comune delle transazioni è recuperare un'entità con una chiave denominata o crearla se non esiste ancora (questo esempio si basa sull'esempio TaskList della creazione di un'entità):

C#

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore C#.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Entity task;
using (var transaction = _db.BeginTransaction())
{
    task = transaction.Lookup(_sampleTask.Key);
    if (task == null)
    {
        transaction.Insert(_sampleTask);
        transaction.Commit();
    }
}

Go

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Go.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
	var task Task
	if err := tx.Get(key, &task); err != datastore.ErrNoSuchEntity {
		return err
	}
	_, err := tx.Put(key, &Task{
		Category:    "Personal",
		Done:        false,
		Priority:    4,
		Description: "Learn Cloud Datastore",
	})
	return err
})

Java

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Java.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Entity task;
Transaction txn = datastore.newTransaction();
try {
  task = txn.get(taskKey);
  if (task == null) {
    task = Entity.newBuilder(taskKey).build();
    txn.put(task);
    txn.commit();
  }
} finally {
  if (txn.isActive()) {
    txn.rollback();
  }
}

Node.js

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Node.js.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

async function getOrCreate(taskKey, taskData) {
  const taskEntity = {
    key: taskKey,
    data: taskData,
  };
  const transaction = datastore.transaction();

  try {
    await transaction.run();
    const [task] = await transaction.get(taskKey);
    if (task) {
      // The task entity already exists.
      await transaction.rollback();
    } else {
      // Create the task entity.
      transaction.save(taskEntity);
      await transaction.commit();
    }
    return taskEntity;
  } catch (err) {
    await transaction.rollback();
  }
}

PHP

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore PHP.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

$transaction = $datastore->transaction();
$entity = $transaction->lookup($task->key());
if ($entity === null) {
    $entity = $transaction->insert($task);
    $transaction->commit();
}

Python

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Python.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

import datetime

with client.transaction():
    key = client.key(
        "Task", datetime.datetime.now(tz=datetime.timezone.utc).isoformat()
    )

    task = client.get(key)

    if not task:
        task = datastore.Entity(key)
        task.update({"description": "Example task"})
        client.put(task)

    return task

Ruby

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Ruby.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

task = nil
datastore.transaction do |tx|
  task = tx.find task_key
  if task.nil?
    task = datastore.entity task_key do |t|
      t["category"] = "Personal"
      t["done"] = false
      t["priority"] = 4
      t["description"] = "Learn Cloud Datastore"
    end
    tx.save task
  end
end

Come in precedenza, è necessaria una transazione per gestire il caso in cui un altro utente stia tentando di creare o aggiornare un'entità con lo stesso ID stringa. Senza una transazione, se l'entità non esiste e due utenti tentano di crearla, il secondo sovrascrive la prima senza sapere che è successo.

Quando una transazione non va a buon fine, puoi chiedere all'app di riprovare fino a quando non va a buon fine oppure puoi lasciare che siano gli utenti a gestire l'errore trasmettendolo al livello dell'interfaccia utente dell'app. Non è necessario creare un ciclo di ripetizione per ogni transazione.

Infine, puoi utilizzare una transazione per leggere uno snapshot coerente di Datastore. Questa opzione può essere utile quando sono necessarie più letture per eseguire il rendering di una pagina o esportare dati che devono essere coerenti. Questi tipi di transazioni sono spesso chiamate transazioni di sola lettura, poiché non eseguono scritture. Le transazioni di gruppo singolo di sola lettura non falliscono mai a causa di modifiche simultanee, quindi non è necessario implementare i tentativi di nuovo in caso di errore. Tuttavia, le transazioni con più gruppi di entità possono non riuscire a causa di modifiche simultanee, pertanto devono essere eseguite delle ripetizioni.

C#

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore C#.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Entity taskList;
IReadOnlyList<Entity> tasks;
using (var transaction = _db.BeginTransaction(TransactionOptions.CreateReadOnly()))
{
    taskList = transaction.Lookup(taskListKey);
    var query = new Query("Task")
    {
        Filter = Filter.HasAncestor(taskListKey)
    };
    tasks = transaction.RunQuery(query).Entities;
    transaction.Commit();
}

Go

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Go.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

tx, err := client.NewTransaction(ctx, datastore.ReadOnly)
if err != nil {
	log.Fatalf("client.NewTransaction: %v", err)
}
defer tx.Rollback() // Transaction only used for read.

ancestor := datastore.NameKey("TaskList", "default", nil)
query := datastore.NewQuery("Task").Ancestor(ancestor).Transaction(tx)
var tasks []Task
_, err = client.GetAll(ctx, query, &tasks)

Java

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Java.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Entity taskList;
QueryResults<Entity> tasks;
Transaction txn =
    datastore.newTransaction(
        TransactionOptions.newBuilder().setReadOnly(ReadOnly.newBuilder().build()).build());
try {
  taskList = txn.get(taskListKey);
  Query<Entity> query =
      Query.newEntityQueryBuilder()
          .setKind("Task")
          .setFilter(PropertyFilter.hasAncestor(taskListKey))
          .build();
  tasks = txn.run(query);
  txn.commit();
} finally {
  if (txn.isActive()) {
    txn.rollback();
  }
}

Node.js

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Node.js.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

async function getTaskListEntities() {
  const transaction = datastore.transaction({readOnly: true});
  try {
    const taskListKey = datastore.key(['TaskList', 'default']);

    await transaction.run();
    const [taskList] = await transaction.get(taskListKey);
    const query = datastore.createQuery('Task').hasAncestor(taskListKey);
    const [taskListEntities] = await transaction.runQuery(query);
    await transaction.commit();
    return [taskList, taskListEntities];
  } catch (err) {
    await transaction.rollback();
  }
}

PHP

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore PHP.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

$transaction = $datastore->readOnlyTransaction();
$taskListKey = $datastore->key('TaskList', 'default');
$query = $datastore->query()
    ->kind('Task')
    ->hasAncestor($taskListKey);
$result = $transaction->runQuery($query);
$taskListEntities = [];
$num = 0;
/* @var Entity $task */
foreach ($result as $task) {
    $taskListEntities[] = $task;
    $num += 1;
}

Python

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Python.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

with client.transaction(read_only=True):
    task_list_key = client.key("TaskList", "default")

    task_list = client.get(task_list_key)

    query = client.query(kind="Task", ancestor=task_list_key)
    tasks_in_list = list(query.fetch())

    return task_list, tasks_in_list

Ruby

Per scoprire come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Ruby.

Per autenticarti a Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

# task_list_name = "default"
task_list_key = datastore.key "TaskList", task_list_name
datastore.read_only_transaction do |tx|
  task_list = tx.find task_list_key
  query = datastore.query("Task").ancestor(task_list)
  tasks_in_list = tx.run query
end

Transazioni e gruppi di entità

Un gruppo di entità è un insieme di entità collegate tramite la parentela a un elemento principale comune. L'organizzazione dei dati in gruppi di entità può limitare le transazioni che possono essere eseguite:

  • Tutti i dati a cui accede una transazione devono essere contenuti in massimo 25 gruppi di entità.
  • Se vuoi utilizzare le query all'interno di una transazione, i dati devono essere organizzati in gruppi di entità in modo da poter specificare filtri di antenato che corrispondano ai dati corretti.
  • Esiste un limite di velocità effettiva di scrittura di circa una transazione al secondo all'interno di un singolo gruppo di entità. Questa limitazione esiste perché Datastore esegue la replica sincrona senza master di ogni gruppo di entità su un'ampia area geografica per garantire elevata affidabilità e tolleranza di errori.

In molte applicazioni, è accettabile utilizzare la coerenza finale (ovvero una query non principale che include più gruppi di entità, che a volte può restituire dati leggermente obsoleti) per ottenere una visione ampia di dati non correlati e poi utilizzare la elevata coerenza (una query da predecessore o un lookup di una singola entità) per visualizzare o modificare un singolo insieme di dati altamente correlati. In queste applicazioni, in genere è consigliabile utilizzare un gruppo di entità distinto per ogni insieme di dati altamente correlati. Per ulteriori informazioni, consulta la sezione Coerenza dei dati.

Passaggi successivi