Indici

Ogni query di Firestore in modalità Datastore calcola i risultati utilizzando uno o più indici che contengono chiavi di entità in una sequenza specificata dalle proprietà dell'indice e, facoltativamente, dai predecessori dell'entità. Gli indici vengono aggiornati per riflettere eventuali modifiche apportate dall'applicazione alle sue entità, in modo che i risultati corretti di tutte le query siano disponibili senza bisogno di ulteriori calcoli.

Esistono due tipi di indici:

Indici integrati
Per impostazione predefinita, un database in modalità Datastore predefinisce automaticamente un indice per ogni proprietà di ogni tipo di entità. Questi indici di proprietà singola sono adatti per tipi di query semplici.
Indici composti
Gli indici composti indicizzano più valori di proprietà per entità indicizzata. Gli indici composti supportano query complesse e sono definiti in un file di configurazione indice (index.yaml).

I tipi di indici vengono discussi in modo più dettagliato in un secondo momento.

Definizione e struttura dell'indice

Un indice viene definito in un elenco di proprietà di un determinato tipo di entità, con un ordine corrispondente (ordine crescente o decrescente) per ogni proprietà. Per l'utilizzo con le query dei predecessori, l'indice può anche includere facoltativamente i predecessori di un'entità.

Un indice contiene voci per ogni proprietà denominata nella definizione dell'indice. Ogni voce dell'indice rappresenta un'entità che è un potenziale risultato per query basate sull'indice. Un'entità è inclusa nell'indice solo se ha un valore indicizzato per ogni proprietà utilizzata nell'indice; se la definizione dell'indice si riferisce a una proprietà per la quale l'entità non ha valore, l'entità non verrà visualizzata nell'indice e quindi non verrà mai restituita come risultato per nessuna query basata sull'indice.

L'indice composto viene ordinato prima per predecessore e poi per valori delle proprietà, nell'ordine specificato nella definizione dell'indice. Sulla base di queste conoscenze, puoi creare l'indice perfetto che consente query efficienti.

Configurazione degli indici

Firestore in modalità Datastore fornisce indici integrati o automatici per le query nei seguenti formati:

  • Query non ordinate utilizzando solo filtri dei predecessori e chiave
  • Query che utilizzano solo filtri di predecessore e di uguaglianza
  • Query che utilizzano solo filtri di disuguaglianza (limitati a una singola proprietà)
  • Query che utilizzano solo filtri dei predecessori, filtri di uguaglianza sulle proprietà e filtri di disuguaglianza sulle chiavi
  • Query senza filtri e con un solo ordinamento per una proprietà, in ordine crescente o decrescente

Ad esempio, per impostazione predefinita, i database in modalità Datastore predefiniscono automaticamente due singoli indici di proprietà per ogni proprietà di ogni tipo di entità, uno in ordine crescente e uno in ordine decrescente. Se non vuoi che il database mantenga un indice per una proprietà, escludi la proprietà dagli indici. Tieni presente che l'esclusione di una proprietà ne comporta la rimozione da tutti gli indici composti.

Gli indici integrati sono sufficienti per eseguire molte query semplici, ad esempio query di sola uguaglianza e semplici query di disuguaglianza.

Gli indici integrati non vengono visualizzati nella pagina Indici della console Google Cloud.

Per query più complesse, un'applicazione deve definire indici compositi o manuali. Gli indici composti sono obbligatori per le query nel formato seguente:

  • Query con filtri di predecessore e di disuguaglianza
  • Query con uno o più filtri di disuguaglianza su una proprietà e uno o più filtri di uguaglianza su altre proprietà
  • Query con ordinamento dei tasti in ordine decrescente
  • Query con più ordini
  • Query con uno o più filtri e uno o più ordini di ordinamento

Gli indici composti sono definiti nel file di configurazione degli indici (index.yaml) dell'applicazione. Il file di configurazione degli indici non contiene gli indici integrati.

Gli indici composti sono composti da più proprietà e richiedono che ogni singola proprietà non venga esclusa dagli indici.

Gli indici composti sono visualizzabili nella pagina Indici della console Google Cloud. Non puoi utilizzare la console Google Cloud per creare o aggiornare indici composti.

Se l'applicazione tenta di eseguire una query che non può essere eseguita con gli indici disponibili (integrati o specificati nel file di configurazione degli indici), la query avrà esito negativo.

L'API Datastore suggerisce automaticamente gli indici appropriati per la maggior parte delle applicazioni. A seconda dell'utilizzo del database in modalità Datastore e delle dimensioni e della forma dei dati da parte dell'applicazione, potrebbero essere garantiti aggiustamenti manuali agli indici. Ad esempio, la scrittura di entità con più valori di proprietà può comportare l'esplosione dell'indice con elevati costi di archiviazione e una maggiore latenza di scrittura.

L'emulatore del datastore può aiutarti a semplificare la gestione del file di configurazione dell'indice. Invece di non riuscire a eseguire una query che richiede un indice e non ne ha uno, l'emulatore Datastore può generare una configurazione di indice che consenta la riuscita della query. Se il test locale di un'applicazione esegue ogni possibile query che verrà emessa dall'applicazione, utilizzando ogni combinazione di filtro e ordinamento, le voci generate rappresenteranno un insieme completo di indici. Se i test non vengono eseguiti su tutti i possibili moduli di query, puoi rivedere e modificare il file di configurazione degli indici prima di aggiornare gli indici.

Per scoprire di più su index.yaml, consulta Configurazione indice.

Deployment o eliminazione degli indici

Quando hai finito di modificare il file di configurazione degli indici, esegui il comando gcloud datastore indexes create per attivare gli indici. Scopri di più sull'aggiornamento degli indici.

Se in precedenza hai eseguito il deployment di indici che non sono più necessari, puoi eliminare gli indici inutilizzati.

Costi di archiviazione e latenza di scrittura

Gli indici contribuiscono ai costi di archiviazione. Dimensione delle voci di indice: descrive in che modo gli indici integrati e composti contribuiscono alla dimensione dello spazio di archiviazione del database. Puoi utilizzare le statistiche di Firestore in modalità Datastore per ulteriori informazioni sulle voci di indice e sulle dimensioni di archiviazione degli indici.

Gli indici contribuiscono anche alla latenza di scrittura. Quando il valore di una proprietà viene aggiornato, il database aggiorna anche ogni indice correlato. Maggiore è il numero di indici che il database deve aggiornare, maggiore è il tempo necessario per l'operazione.

Puoi ridurre i costi di archiviazione e migliorare le prestazioni di scrittura eliminando gli indici inutilizzati ed escludendo le proprietà dall'indicizzazione. Questo inoltre impedisce che le operazioni non vadano a buon fine a causa dei limiti dell'indice.

Indici e proprietà

Di seguito sono riportate alcune considerazioni speciali da tenere presenti sugli indici e sulla loro relazione con le proprietà delle entità:

Proprietà con tipi di valori misti

Quando due entità hanno proprietà con lo stesso nome ma tipi di valore diversi, un indice di questa proprietà ordina le entità prima in base al tipo di valore e poi in base a un ordinamento secondario appropriato per ogni tipo. Ad esempio, se due entità hanno ciascuna una proprietà denominata age, una con un valore intero e una con un valore stringa, l'entità con valore intero precede sempre quella con il valore stringa quando ordinata in base alla proprietà age, indipendentemente dai valori della proprietà stessi.

Questo vale soprattutto per i numeri interi e in virgola mobile, che vengono trattati come tipi separati dalla modalità Datastore. Poiché tutti i numeri interi vengono ordinati prima di tutti i valori in virgola mobile, una proprietà con valore intero 38 viene ordinata prima di quella con valore in virgola mobile 37.5.

Proprietà escluse

Se sai che non dovrai mai filtrare o ordinare in base a una determinata proprietà, puoi dire al tuo database in modalità Datastore di non mantenere le voci di indice per quella proprietà escludendola dagli indici. Questo riduce i costi di esecuzione dell'applicazione diminuendo lo spazio di archiviazione necessario per le voci di indice. Ciò può anche migliorare la latenza di scrittura. Un'entità con una proprietà esclusa si comporta come se la proprietà non fosse impostata: le query con un filtro o un ordinamento nella proprietà esclusa non corrisponderanno mai a questa entità.

La proprietà description nell'esempio seguente è esclusa dagli indici:

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Entity task = new Entity()
{
    Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
    ["category"] = "Personal",
    ["created"] = new DateTime(1999, 01, 01, 0, 0, 0, DateTimeKind.Utc),
    ["done"] = false,
    ["priority"] = 4,
    ["percent_complete"] = 10.0,
    ["description"] = new Value()
    {
        StringValue = "Learn Cloud Datastore",
        ExcludeFromIndexes = true
    },
};

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

type Task struct {
	Category        string
	Done            bool
	Priority        int
	Description     string `datastore:",noindex"`
	PercentComplete float64
	Created         time.Time
}
task := &Task{
	Category:        "Personal",
	Done:            false,
	Priority:        4,
	Description:     "Learn Cloud Datastore",
	PercentComplete: 10.0,
	Created:         time.Now(),
}

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Entity task =
    Entity.newBuilder(taskKey)
        .set("category", "Personal")
        .set("created", Timestamp.now())
        .set("done", false)
        .set("priority", 4)
        .set("percent_complete", 10.0)
        .set(
            "description",
            StringValue.newBuilder("Learn Cloud Datastore").setExcludeFromIndexes(true).build())
        .build();

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

const task = [
  {
    name: 'category',
    value: 'Personal',
  },
  {
    name: 'created',
    value: new Date(),
  },
  {
    name: 'done',
    value: false,
  },
  {
    name: 'priority',
    value: 4,
  },
  {
    name: 'percent_complete',
    value: 10.0,
  },
  {
    name: 'description',
    value: 'Learn Cloud Datastore',
    excludeFromIndexes: true,
  },
];

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

$task = $datastore->entity(
    $key,
    [
        'category' => 'Personal',
        'created' => new DateTime(),
        'done' => false,
        'priority' => 4,
        'percent_complete' => 10.0,
        'description' => 'Learn Cloud Datastore'
    ],
    ['excludeFromIndexes' => ['description']]
);

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori 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()

key = client.key("Task")
task = datastore.Entity(key, exclude_from_indexes=("description",))
task.update(
    {
        "category": "Personal",
        "description": "Learn Cloud Datastore",
        "created": datetime.datetime.now(tz=datetime.timezone.utc),
        "done": False,
        "priority": 4,
        "percent_complete": 10.5,
    }
)
client.put(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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

task = datastore.entity "Task" do |t|
  t["category"] = "Personal"
  t["created"] = Time.now
  t["done"] = false
  t["priority"] = 4
  t["percent_complete"] = 10.0
  t["description"] = "Learn Cloud Datastore"
  t.exclude_from_indexes! "description", true
end

GQL

Non applicabile

La query nell'esempio seguente non restituirà alcun risultato se la proprietà description è stata esclusa:

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Query query = new Query("Task")
{
    Filter = Filter.Equal("description", "Learn Cloud Datastore")
};

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

query := datastore.NewQuery("Tasks").
	FilterField("Description", "=", "A task description")

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Query<Entity> query =
    Query.newEntityQueryBuilder()
        .setKind("Task")
        .setFilter(PropertyFilter.eq("description", "A task description"))
        .build();

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

const query = datastore
  .createQuery('Task')
  .filter(new PropertyFilter('description', '=', 'A task description.'));

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

$query = $datastore->query()
    ->kind('Task')
    ->filter('description', '=', 'A task description.');

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori 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()

query = client.query(kind="Task")
query.add_filter(filter=PropertyFilter("description", "=", "Learn Cloud Datastore"))

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

query = datastore.query("Task")
                 .where("description", "=", "A task description.")

GQL


# Will not return any results!
SELECT * FROM Task WHERE description = 'A task description.'

In un secondo momento puoi reimpostare la proprietà su indicizzata.

Tuttavia, tieni presente che la modifica di una proprietà da esclusa a indicizzata non influisce sulle entità esistenti che potrebbero essere state create prima della modifica. Le query che filtrano la proprietà non restituiranno queste entità esistenti, perché queste non sono state scritte nell'indice della query al momento della creazione. Per rendere le entità accessibili dalle query future, devi riscriverle nel tuo database in modo che vengano inserite negli indici appropriati. Ciò significa che devi eseguire le seguenti operazioni per ciascuna entità esistente:

  1. Cerca l'entità.
  2. Scrivi (put) di nuovo l'entità nel database.

Analogamente, la modifica di una proprietà da indicizzata a esclusa influisce solo sulle entità scritte successivamente nel database. Le voci di indice relative a qualsiasi entità esistente con quella proprietà continueranno a esistere fino a quando le entità non verranno aggiornate o eliminate. Per evitare risultati indesiderati, devi eliminare definitivamente il codice di tutte le query che filtrano o ordinano in base alla proprietà (ora esclusa).

Limiti dell'indice

Firestore in modalità Datastore impone dei limiti al numero e alla dimensione complessiva delle voci di indice che possono essere associate a una singola entità. Questi limiti sono grandi e la maggior parte delle applicazioni non sono interessate. Tuttavia, in alcune circostanze potresti riscontrare dei limiti.

Come descritto sopra, un database in modalità Datastore crea una voce in un indice predefinito per ogni proprietà di ogni entità, tranne quelle che hai dichiarato esplicitamente come escluse dagli indici. La proprietà può anche essere inclusa in altri indici personalizzati dichiarati nel file di configurazione degli indici (index.yaml). Purché un'entità non abbia proprietà di elenco, avrà al massimo una voce in ogni indice personalizzato (per gli indici non predecessori) o una per ciascuno dei predecessori dell'entità (per gli indici predecessori). Ognuna di queste voci di indice deve essere aggiornata ogni volta che il valore della proprietà cambia.

Per una proprietà con un singolo valore per ogni entità, ogni possibile valore deve essere archiviato una sola volta per ciascuna entità nell'indice predefinito della proprietà. Anche in questo caso, è possibile che un'entità con un numero elevato di tali proprietà a valore singolo superi il limite di voce di indice o dimensione. Analogamente, un'entità che può avere più valori per la stessa proprietà richiede una voce di indice distinta per ogni valore; di nuovo, se il numero di valori possibili è elevato, tale entità può superare il limite di voci.

La situazione peggiora nel caso di entità con più proprietà, ciascuna delle quali può assumere più valori. Per contenere un'entità di questo tipo, l'indice deve includere una voce per ogni possibile combinazione di valori della proprietà. Gli indici personalizzati che fanno riferimento a più proprietà, ciascuna con più valori, possono "esplodere" in modo combinatorio, richiedendo un numero elevato di voci per un'entità con solo un numero relativamente ridotto di possibili valori di proprietà. Questi indici esplosivi possono aumentare drasticamente le dimensioni dello spazio di archiviazione di un'entità, a causa dell'elevato numero di voci di indice che devono essere archiviate. L'esplosione degli indici può anche causare il superamento del numero di voci di indice o del limite di dimensione da parte dell'entità.

Considera il seguente codice:

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Entity task = new Entity()
{
    Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
    ["tags"] = new ArrayValue() { Values = { "fun", "programming", "learn" } },
    ["collaborators"] = new ArrayValue() { Values = { "alice", "bob", "charlie" } },
    ["created"] = DateTime.UtcNow
};

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

task := &Task{
	Tags:          []string{"fun", "programming", "learn"},
	Collaborators: []string{"alice", "bob", "charlie"},
	Created:       time.Now(),
}

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

Entity task =
    Entity.newBuilder(taskKey)
        .set("tags", "fun", "programming", "learn")
        .set("collaborators", "alice", "bob", "charlie")
        .set("created", Timestamp.now())
        .build();

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

const task = {
  method: 'insert',
  key: datastore.key('Task'),
  data: {
    tags: ['fun', 'programming', 'learn'],
    collaborators: ['alice', 'bob', 'charlie'],
    created: new Date(),
  },
};

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

$task = $datastore->entity(
    $datastore->key('Task'),
    [
        'tags' => ['fun', 'programming', 'learn'],
        'collaborators' => ['alice', 'bob', 'charlie'],
        'created' => new DateTime(),
    ]
);

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori 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()

task = datastore.Entity(client.key("Task"))
task.update(
    {
        "tags": ["fun", "programming", "learn"],
        "collaborators": ["alice", "bob", "charlie"],
        "created": datetime.datetime.now(tz=datetime.timezone.utc),
    }
)

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 eseguire l'autenticazione in Cloud Datastore, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

task = datastore.entity "Task" do |t|
  t["tags"] = ["fun", "programming", "learn"]
  t["collaborators"] = ["alice", "bob", "charlie"]
  t["created"] = Time.now
end

GQL

Non applicabile

Viene creata un'entità Task con tre valori per la proprietà tags, tre valori per la proprietà collaborators e created impostati sulla data corrente. Saranno necessarie nove voci di indice, una per ogni possibile combinazione di valori di proprietà:

('fun', 'alice', NOW())
('fun', 'bob', NOW())
('fun', 'charlie', NOW())

('programming', 'alice', NOW())
('programming', 'bob', NOW())
('programming', 'charlie', NOW())

('learn', 'alice', NOW())
('learn', 'bob', NOW())
('learn', 'charlie', NOW())

Quando la stessa proprietà viene ripetuta più volte, Firestore in modalità Datastore può rilevare gli indici che esplodono e suggerire un indice alternativo. Tuttavia, in tutte le altre circostanze (come la query definita in questo esempio), un database in modalità Datastore genererà un indice enorme. In questo caso, puoi aggirare lindice enorme dell'indice configurando manualmente un indice nel file di configurazione dell'indice:

indexes:
- kind: Task
  properties:
  - name: tags
  - name: created
- kind: Task
  properties:
  - name: collaborators
  - name: created

In questo modo il numero di voci necessario viene ridotto a (|tags| * |created| + |collaborators| * |created|) o a 6 voci anziché 9:

('fun', NOW())
('programming', NOW())
('learn', NOW())

('alice', NOW())
('bob', NOW())
('charlie', NOW())

Qualsiasi operazione commit che comporterebbe il superamento della voce di indice o del limite di dimensioni da parte di un indice non andrà a buon fine. Il testo dell'errore descrive quale limite è stato superato ("Too many indexed properties" o "Index entries too large") e quale indice personalizzato ne è stata la causa. Se crei un nuovo indice che supererebbe i limiti per qualsiasi entità quando viene creato, le query sull'indice avranno esito negativo e l'indice verrà visualizzato nello stato Error nella console Google Cloud. Per gestire questi indici Error,

  1. Rimuovi l'indice dal file di configurazione dell'indice (index.yaml).
  2. Utilizzando Google Cloud CLI, rimuovi l'indice dal database utilizzando il comando datastore indexes cleanup, come descritto in Eliminazione degli indici inutilizzati.
  3. Uno dei due
    • riformulare la definizione dell'indice e le query corrispondenti, oppure
    • rimuovi le entità che causano l'esplosione dell'indice.
  4. Aggiungi di nuovo l'indice a index.yaml.
  5. Utilizzando Google Cloud CLI, aggiungi l'indice al database eseguendo il comando datastore indexes create, come descritto in Aggiornare gli indici.

Puoi evitare di esplodere gli indici evitando di eseguire query che richiederebbero un indice personalizzato utilizzando una proprietà elenco. Come descritto in precedenza, sono incluse le query con più ordini di ordinamento oppure con una combinazione di filtri di uguaglianza e disuguaglianza.

Indici per le proiezioni

Le query di proiezione richiedono che tutte le proprietà specificate nella proiezione siano incluse in un indice. L'emulatore di datastore genera automaticamente gli indici necessari nel file di configurazione degli indici, index.yaml, che viene caricato con la tua applicazione.

Un modo per ridurre al minimo il numero di indici richiesti è proiettare le stesse proprietà in modo coerente, anche quando non sono sempre necessarie. Ad esempio, queste query richiedono due indici distinti:

SELECT priority, percent_complete FROM Task

SELECT priority, percent_complete, created FROM Task

Tuttavia, se progetti sempre le proprietà priority, percent_complete e created, anche quando created non è obbligatorio, sarà necessario un solo indice.

La conversione di una query esistente in una query di proiezione potrebbe richiedere la creazione di un nuovo indice se le proprietà della proiezione non sono già incluse in un'altra parte della query. Ad esempio, supponiamo che tu abbia una query esistente come

SELECT * FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

che richiede l'indice:

indexes:
- kind: Task
  properties:
  - name: priority
  - name: percent_complete

Conversione in una delle query di proiezione

SELECT created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

SELECT priority, percent_complete, created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

introduce una nuova proprietà (created) e richiede quindi la creazione di un nuovo indice:

indexes:
- kind: Task
  properties:
  - name: priority
  - name: percent_complete
  - name: created

Tuttavia,

SELECT priority, percent_complete FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

non modificherebbe l'indice richiesto, poiché le proprietà previste priority e percent_complete erano già incluse nella query esistente.

Più database

Puoi utilizzare gcloud firestore per gestire un singolo indice per la modalità Datastore o gcloud datastore con un file index.yaml per gestire tutti gli indici in un database.

gcloud firestore
gcloud firestore indexes composite create --api-scope=datastore-mode-api  --query-scope=QUERY_SCOPE --database=DATABASE_ID
gcloud datastore
gcloud alpha datastore indexes create index.yaml --database=DATABASE_ID

Sostituisci quanto segue:

  • DATABASE_ID: un ID database.
  • QUERY_SCOPE: collection-recursive per gli indici predecessori o collection-group per gli indici non predecessori.