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, dagli antenati 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 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 dell'indice (index.yaml).

I tipi di indici sono descritti più dettagliatamente di seguito.

Definizione e struttura dell'indice

Un indice è definito in un elenco di proprietà di un determinato tipo di entità, con un ordine corrispondente (crescente o decrescente) per ogni proprietà. Per l'utilizzo con le query sugli antenati, l'indice può includere facoltativamente anche gli antenati 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 le query basate sull'indice. Un'entità viene inclusa nell'indice solo se ha un valore indicizzato impostato per ogni proprietà utilizzata nell'indice. Se la definizione dell'indice fa riferimento a una proprietà per la quale l'entità non ha un valore, l'entità non verrà visualizzata nell'indice e, di conseguenza, non verrà mai restituita come risultato per qualsiasi query basata sull'indice.

L'indice composto viene ordinato prima in base all'antenato e poi in base ai valori delle proprietà, nell'ordine specificato nella definizione dell'indice. In base a questa conoscenza, puoi creare l'indice perfetto che consente query efficienti.

Configurazione degli indici

Firestore in modalità Datastore fornisce indici integrati o automatici per le query dei seguenti tipi:

  • Query senza tipo che utilizzano solo filtri di tipo ancestor e key
  • Query che utilizzano solo filtri di eguaglianza e antenato
  • Query che utilizzano solo filtri di disuguaglianza (limitati a una singola proprietà)
  • Query che utilizzano solo filtri di antenati, filtri di uguaglianza sulle proprietà e filtri di disuguaglianza sulle chiavi
  • Query senza filtri e con un solo ordinamento per una proprietà, crescente o decrescente

Ad esempio, per impostazione predefinita, i database in modalità Datastore predefiniscono automaticamente due indici di proprietà singole 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à comporta la sua rimozione da tutti gli indici composti.

Gli indici incorporati sono sufficienti per eseguire molte query semplici, come query solo di 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 composti o manuali. Gli indici composti sono obbligatori per le query del seguente tipo:

  • Query con filtri di antenato e di diseguaglianza
  • Query con uno o più filtri di disuguaglianza su una proprietà e uno o più filtri di uguaglianza su altre proprietà
  • Query con un ordinamento delle chiavi in ordine decrescente
  • Query con più ordini di ordinamento
  • Query con uno o più filtri e uno o più ordini di ordinamento

Gli indici composti sono definiti nel file di configurazione dell'indice (index.yaml) dell'applicazione. Gli indici integrati non sono contenuti nel file di configurazione dell'indice.

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

Gli indici compositi sono visibili nella pagina Indici della console Google Cloud. Non puoi utilizzare la console Google Cloud per creare o aggiornare gli 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 dell'indice), la query non andrà a buon fine.

L'API della modalità Datastore suggerisce automaticamente gli indici appropriati per la maggior parte delle applicazioni. A seconda dell'utilizzo da parte dell'applicazione del database in modalità Datastore e delle dimensioni e della forma dei dati, regolazioni manuali ai tuoi indici possono essere garantite. Ad esempio, scrivere entità con più valori delle proprietà può causare un indice esplosivo con elevati costi di archiviazione e un aumento della latenza di scrittura.

L'emulatore Datastore può aiutarti a gestire più facilmente il 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 dell'indice che consenta il completamento della query. Se il test locale di un'applicazione esegue ogni possibile query inviata dall'applicazione, utilizzando ogni combinazione di filtro e ordinamento, le voci generate rappresenteranno un insieme completo di indici. Se il test non si esercita ogni possibile modulo di query, puoi rivedere e modificare il file di configurazione dell'indice prima di aggiornare gli indici.

Scopri di più su index.yaml in Configurazione dell'indice.

Implementazione o eliminazione di indici

Al termine della modifica del file di configurazione dell'indice, esegui il comando gcloud datastore indexes create per mettere in servizio gli indici. Scopri di più sull'aggiornamento degli indici.

Se in precedenza hai implementato 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. Dimensioni delle voci di indice descrive in che modo gli indici integrati e composti contribuiscono alle dimensioni dello spazio di archiviazione del database. Puoi utilizzare le statistiche di Firestore in modalità Datastore per visualizzare ulteriori informazioni sulle voci di indice e sulle dimensioni dello spazio di archiviazione degli indici.

Anche gli indici contribuiscono alla latenza di scrittura. Quando aggiorni un valore della proprietà, il database aggiorna anche ogni indice correlato. Più indici deve aggiornare il database, più tempo richiede l'operazione.

Puoi ridurre i costi di archiviazione e migliorare le prestazioni di scrittura eliminando gli indici inutilizzati e escludendo le proprietà dall'indicizzazione. In questo modo si evita anche che le operazioni non vadano a buon fine a causa di limiti di indice.

Indici e proprietà

Ecco 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 della proprietà ordina le entità innanzitutto 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 di stringa, l'entità con il valore intero precede sempre quella con il valore di stringa quando l'ordinamento avviene in base alla proprietà age, indipendentemente dai valori delle proprietà stesse.

Questo è particolarmente importante nel caso di numeri interi e a virgola mobile, che vengono trattati come tipi distinti dalla modalità Datastore. Poiché tutti i numeri interi vengono ordinati prima di tutti i numeri in virgola mobile, una proprietà con il valore intero 38 viene ordinata prima di una con il valore in virgola mobile 37.5.

Proprietà escluse

Se sai che non dovrai mai filtrare o ordinare in base a una determinata proprietà, puoi indicare al database in modalità Datastore di non gestire le voci dell'indice per quella proprietà escludendola dagli indici. In questo modo si riduce il costo di esecuzione dell'applicazione riducendo le dimensioni dello spazio di archiviazione necessarie per le voci dell'indice. In questo modo puoi 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 ordine di ordinamento nella proprietà esclusa non corrisponderanno mai a quell'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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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()

import datetime

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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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=datastore.query.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 autenticarti a Cloud Datastore, configura le 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 ripristinare lo stato indicizzato della proprietà.

Tieni presente, tuttavia, 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 in base alla proprietà non restituiranno queste entità esistenti, perché non sono state scritte nell'indice della query al momento della loro creazione. Per rendere le entità accessibili dalle query future, devi riscriverle nel database in modo che vengano inserite negli indici appropriati. In altre parole, devi eseguire le seguenti operazioni per ogni entità esistente:

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

Analogamente, la modifica di una proprietà da indicizzata a esclusa interessa solo le entità successivamente scritte nel database. Le voci di indice per le entità esistenti con questa proprietà continueranno a esistere finché le entità non vengono aggiornate o eliminate. Per evitare risultati indesiderati, devi eliminare dal codice tutte le query che filtrano o ordinano in base alla proprietà (ora esclusa).

Limiti per gli indici

Firestore in modalità Datastore impone limiti al numero e alle dimensioni complessive delle voci di indice che possono essere associate a una singola entità. Questi limiti sono elevati e la maggior parte delle applicazioni non è interessata. Tuttavia, ci sono circostanze in cui 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 per quelle che hai dichiarato esplicitamente come escluse dagli indici. La proprietà può essere inclusa anche in altri indici personalizzati dichiarati nel file di configurazione dell'indice (index.yaml). Se un'entità non ha proprietà elenco, avrà al massimo una voce in ciascun indice personalizzato (per gli indici non predecessori) o una per ciascuno dei predecessori dell'entità (per gli indici dei predecessori). Ognuna di queste voci di indice va aggiornata ogni volta che cambia il valore della proprietà.

Per una proprietà con un singolo valore per ogni entità, ogni valore possibile deve essere archiviato una sola volta per entità nell'indice predefinito della proprietà. Tuttavia, è possibile che un'entità con un numero elevato di proprietà con un solo valore superi il limite di dimensioni o di voci dell'indice. Analogamente, un'entità che può avere più valori per la stessa proprietà richiede una voce dell'indice separata per ogni valore. Anche in questo caso, se il numero di valori possibili è elevato, un'entità di questo tipo può superare il limite di voci.

La situazione peggiora nel caso di entità con più proprietà, ciascuna delle quali può assumere più valori. Per supportare un'entità di questo tipo, l'indice deve includere una voce per ogni possibile combinazione di valori delle 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 delle proprietà. Questi indici esplosivi possono aumentare notevolmente le dimensioni dello spazio di archiviazione di un'entità, a causa del numero elevato di voci di indice da archiviare. Gli indici esplosi possono anche causare il superamento del limite di dimensioni o del numero di voci dell'indice 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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 autenticarti a Cloud Datastore, configura le 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()

import datetime

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 autenticarti a Cloud Datastore, configura le 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

Crea un'entità Task con tre valori per la proprietà tags, tre valori per la proprietà collaborators e created impostato sulla data corrente. Sono necessarie nove voci di indice, una per ogni possibile combinazione di valori delle 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 in crescita esponenziale e suggerire un indice alternativo. Tuttavia, in tutte le altre circostanze (ad esempio la query definita in questo esempio), un database in modalità Datastore genererà un indice enorme. In questo caso, puoi aggirare l'indice enorme 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 necessarie si riduce a (|tags| * |created| + |collaborators| * |created|), ovvero 6 voci anziché 9:

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

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

Qualsiasi operazione commit che causerebbe il superamento del limite di dimensioni o di voci dell'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 è stato la causa. Se crei un nuovo indice che supererebbe i limiti per qualsiasi entità al momento della compilazione, le query sull'indice non andranno a buon fine 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 Eliminare gli indici inutilizzati.
  3. Uno dei seguenti modi:
    • 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 Aggiornamento degli indici.

Puoi evitare di creare indici troppo grandi evitando le query che richiederebbero un indice personalizzato utilizzando una proprietà elenco. Come descritto in precedenza, sono incluse le query con più ordini di ordinamento o 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 Datastore genera automaticamente gli indici necessari nel file di configurazione dell'indice index.yaml, che viene caricato con l'applicazione.

Un modo per ridurre al minimo il numero di indici richiesti è proiettare le stesse proprietà in modo coerente, anche se non tutte 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 proietti sempre le proprietà priority, percent_complete, created, anche quando created non è obbligatoria, 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à nella 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

Convertendo questo valore 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 quindi richiede 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 cambierebbe l'indice richiesto, poiché le proprietà proiettate 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 firestore con un file index.yaml per gestire tutti gli indici di un database.gcloud datastore

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 di antenati o collection-group per gli indici non di antenati.