Indici

Ogni query 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 le modifiche apportate dall'applicazione alle sue entità, in modo che i risultati corretti di tutte le query siano disponibili senza ulteriori calcoli necessari.

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 a singola proprietà sono adatti a tipi semplici di query.
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 vengono trattati in modo più dettagliato in un secondo momento.

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ò anche includere facoltativamente 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 quindi non verrà mai restituita come risultato per qualsiasi query basata sull'indice.

L'indice composto viene ordinato prima per antenato e poi per valori delle proprietà, nell'ordine specificato nella definizione dell'indice. In base a questa comprensione, 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 per predecessore e chiave
  • Query che utilizzano solo filtri di uguaglianza e antenati
  • Query che utilizzano solo filtri di disuguaglianza (che sono 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 di una proprietà, crescente o decrescente

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

Gli indici incorporati sono sufficienti per eseguire molte query semplici, come query di sola uguaglianza e query di disuguaglianza semplici.

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 compositi sono obbligatori per le query del seguente formato:

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

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

Gli indici compositi sono composti 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 indici compositi.

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, dimensioni e forma dei dati, regolazioni manuali agli indici possono essere garantite. Ad esempio, scrivere entità con più valori delle proprietà può causare un indice esplosivo con costi di archiviazione elevati e una maggiore latenza di scrittura.

L'emulatore Datastore può 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 dell'indice che consentirebbe 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.

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

Deployment 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ù nella pagina Aggiornare gli indici.

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

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 di archiviazione del database. Puoi utilizzare le statistiche di Firestore in modalità Datastore per visualizzare ulteriori informazioni sulle voci di indice e sulle dimensioni di archiviazione dell'indice.

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 dei limiti di indice.

Indici e proprietà

Ecco alcune considerazioni speciali da tenere a mente sugli indici e sul loro rapporto con le proprietà delle entità:

Proprietà con tipi di valori misti

Quando due entità hanno proprietà con lo stesso nome ma tipi di valori diversi, un indice della 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 il valore intero precede sempre quella con il valore stringa quando vengono ordinate in base alla proprietà age, indipendentemente dai valori della proprietà.

Ciò è particolarmente importante nel caso di 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 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 mantenere le voci di indice per quella proprietà escludendola dagli indici. In questo modo si riduce il costo di esecuzione dell'applicazione diminuendo le dimensioni di archiviazione necessarie 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 sulla proprietà esclusa non corrisponderanno mai a quell'entità.

La proprietà description nel seguente esempio è esclusa dagli indici:

C#

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

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Go.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Java.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Node.js.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore PHP.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Python.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Ruby.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore C#.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Go.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Java.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Node.js.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore PHP.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Python.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Ruby.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 impostare di nuovo l'indicizzazione 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 di filtro sulla proprietà non restituiranno queste entità esistenti, perché 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. ovvero devi eseguire le seguenti operazioni per ogni entità esistente:

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

Allo stesso modo, la modifica di una proprietà da indicizzata a esclusa influisce solo sulle entità scritte successivamente nel database. Le voci di indice per le entità esistenti con quella 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 degli 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, esistono circostanze in cui potresti raggiungere i 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 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à che ha un singolo valore per ogni entità, ogni valore possibile deve essere archiviato una sola volta per entità nell'indice predefinito della proprietà. Ciò nonostante, è possibile che un'entità con un numero elevato di proprietà a valore singolo superi il limite di dimensioni o di voci dell'indice. Allo stesso modo, un'entità che può avere più valori per la stessa proprietà richiede una voce di indice separata per ogni valore; anche in questo caso, se il numero di valori possibili è elevato, un'entità può superare il limite di voci.

La situazione peggiora nel caso di entità con più proprietà, ognuna delle quali può assumere più valori. Per ospitare un'entità di questo tipo, l'indice deve includere una voce per ogni combinazione possibile 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 un numero relativamente piccolo di valori di proprietà possibili. Questi indici esplosivi possono aumentare notevolmente le dimensioni di archiviazione di un'entità, a causa del gran numero di voci di indice che devono essere archiviate. Gli indici in espansione possono anche causare il superamento del limite di dimensioni o di conteggio delle voci dell'indice per l'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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore C#.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Go.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Java.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Node.js.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore PHP.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Python.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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 saperne di più, consulta la documentazione di riferimento dell'API Cloud Datastore Ruby.

Per eseguire l'autenticazione in Cloud Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura 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. Ciò richiederà 9 voci di indice, una per ogni combinazione possibile 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 indici esplosivi 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 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 sole (|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 è la causa. Se crei un nuovo indice che supererebbe i limiti per qualsiasi entità al momento della creazione, 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 Eliminazione degli indici inutilizzati.
    • riformulare la definizione dell'indice e le query corrispondenti oppure
    • rimuovi le entità che causano l'esplosione dell'indice.
  3. Aggiungi di nuovo l'indice a index.yaml.
  4. Utilizzando Google Cloud CLI, aggiungi l'indice al database eseguendo il comando datastore indexes create, come descritto in Aggiornamento degli indici.

Puoi evitare l'esplosione degli indici evitando query che richiederebbero un indice personalizzato che utilizza una proprietà elenco. Come descritto in precedenza, sono incluse le query con più criteri di ordinamento o con un mix 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 quando non sono sempre necessarie. Ad esempio, queste query richiedono due indici separati:

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 di avere 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 pertanto richiederà 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à 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 oppure utilizzare gcloud datastore con un file index.yaml per gestire tutti gli indici di 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 degli antenati o collection-group per gli indici non antenati.