Indici

Ogni query in modalità Datastore in Firestore calcola i risultati utilizzando uno o più indici contenenti chiavi di entità in una sequenza specificata dalle proprietà dell'indice e, facoltativamente, i predecessori dell'entità. Gli indici sono aggiornati per riflettere qualsiasi modifica apportata dall'applicazione alle sue entità, in modo che i risultati corretti di tutte le query siano disponibili senza ulteriori calcoli necessaria.

Esistono due tipi di indici:

Indici integrati
Per impostazione predefinita, un database in modalità Datastore predefinisce automaticamente un indice per ogni proprietà di ciascun 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 ciascuna entità indicizzata. Gli indici composti supportano query complesse e sono definiti in un file di configurazione dell'indice (index.yaml).

I tipi di indici saranno discussi più in dettaglio più avanti.

Definizione e struttura dell'indice

Un indice è definito su 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 predecessori, l'indice può anche includere 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 di query basate sull'indice. Un'entità è inclusa nell'indice solo se ha un valore indicizzato impostato 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 qualsiasi query basata sull'indice.

L'indice composto viene ordinato prima dal predecessore e poi dai valori delle proprietà, nell'ordine specificato nella definizione dell'indice. Sulla base di queste informazioni, è possibile 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 dei predecessori e di uguaglianza
  • Query che utilizzano solo filtri di disuguaglianza (che sono limitati a una singola proprietà)
  • Query che utilizzano solo filtri dei predecessori, filtri di uguaglianza sulle proprietà e filtri di disuguaglianza nelle chiavi
  • Query senza filtri e con un solo ordinamento per proprietà, crescente o decrescente

Ad esempio, per impostazione predefinita, i database in modalità Datastore predefiniscono automaticamente due indici singoli di proprietà per ogni proprietà di ciascun tipo di entità, uno in ordine crescente e uno in ordine decrescente. Se non vuoi che il database conservi un indice di 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 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 dei predecessori e della 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 ordinamento delle chiavi in ordine decrescente
  • Query con più ordini di ordinamento
  • Query con uno o più filtri e uno o più ordinamenti

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

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

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

L'API in modalità 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 garantite regolazioni manuali degli indici. 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ò 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 consenta il completamento della query. Se il test locale di un'applicazione esegue ogni possibile query che verrà generata dall'applicazione, utilizzando ogni combinazione di filtro e ordinamento, le voci generate rappresenteranno un insieme completo di indici. Se il test non esegue tutti i possibili moduli di query, puoi rivedere e modificare il file di configurazione dell'indice prima di aggiornare gli indici.

Per ulteriori informazioni su index.yaml, consulta la pagina Configurazione dell'indice.

Deployment o eliminazione degli indici

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

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

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 Firestore nelle statistiche in modalità Datastore per 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 il valore di una proprietà, il database aggiorna anche ogni indice correlato. Più indici più tempo richiede l'aggiornamento del database.

Puoi ridurre i costi di archiviazione e migliorare le prestazioni di scrittura eliminare gli indici non utilizzati ed 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à

Di seguito sono riportate alcune considerazioni speciali da tenere presenti sugli indici e sulla loro correlazione 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 per 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.

Ciò è particolarmente degno di nota 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 valore intero 38 viene ordinata prima di una proprietà 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 indicare alla modalità Datastore per non mantenere le voci di indice della proprietà in questione 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. È inoltre possibile 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore C# documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 ulteriori informazioni, consulta API Cloud Datastore Go documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Java documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Node.js documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore PHP documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Python documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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()

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 informazioni su 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 le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore C# documentazione di riferimento.

Per autenticarti a Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Go documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

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

Java

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

Per autenticarti a Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Node.js documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 ulteriori informazioni, consulta API Cloud Datastore PHP documentazione di riferimento.

Per autenticarti a Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi Configura l'autenticazione per un ambiente di sviluppo locale.

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

Python

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

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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=PropertyFilter("description", "=", "Learn Cloud Datastore"))

Ruby

Per informazioni su 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 le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 potrai reimpostare la proprietà come indicizzata.

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 per query future, devi riscriverle in modo che vengano inseriti negli indici appropriati. Ciò significa che devi procedere come segue per ciascuna di queste entità esistenti:

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

Analogamente, la modifica di una proprietà da indicizzata ad esclusa interessa solo le entità scritte successivamente nel database. Le voci di indice per tutte le entità esistenti con quella proprietà continueranno a esistere finché 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 indice

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 ne è interessato. Tuttavia, in alcuni casi potresti riscontrare i limiti.

Come descritto sopra, un database in modalità Datastore crea una voce in un indice predefinito per ogni proprietà di ogni entità, ad eccezione di quelle che hai dichiarato esplicitamente come escluse dai tuoi indici. La proprietà può anche essere inclusa in altri indici personalizzati dichiarati nel file di configurazione dell'indice (index.yaml). A condizione che un'entità non abbia 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 deve essere aggiornata ogni volta che il valore della proprietà cambia.

Per una proprietà che ha un singolo valore per ciascuna entità, ogni valore possibile deve essere archiviato una sola volta per 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 dimensioni o la voce di indice. Analogamente, un'entità che può avere più valori per la stessa proprietà richiede una voce di indice separata per ciascun valore. sempre, se il numero di valori possibili è elevato, l'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 includere questa entità, l'indice deve includere una voce per ogni possibile combinazione di valori delle proprietà. Gli indici personalizzati che fanno riferimento a più proprietà, ognuna con più valori, possono "esplodere" combinatoricamente, richiedendo un numero elevato di voci per una con un numero relativamente ridotto di possibili valori di 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 che devono essere archiviate. L'esplosione degli indici può inoltre causare il superamento del limite di dimensioni o del numero di voci di indice.

Considera il seguente codice:

C#

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

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Go documentazione di riferimento.

Per autenticarti a Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Java documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Cloud Datastore Node.js.

Per autenticarti a Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore PHP documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi 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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Python documentazione di riferimento.

Per eseguire l'autenticazione in Cloud Datastore, configura le credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

from google.cloud import datastore

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

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 informazioni su come installare e utilizzare la libreria client per Cloud Datastore, consulta Librerie client di Cloud Datastore. Per ulteriori informazioni, consulta API Cloud Datastore Ruby documentazione di riferimento.

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

task = 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 impostati sulla data corrente. Sono necessarie 9 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 esplosivo. In questo caso, puoi evitare l'indice enorme configurandolo manualmente nel file di configurazione dell'indice:

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

In questo modo si riduce il numero di voci necessarie a solo (|tags| * |created| + |collaborators| * |created|) oppure a 6 voci invece di 9:

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

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

Qualsiasi operazione commit che comporterebbe il superamento della voce dell'indice o il limite di dimensioni di un indice non riuscirà. 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. Con Google Cloud CLI, rimuovi l'indice dal database utilizzando il comando datastore indexes cleanup, come descritto in Eliminazione degli 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 Aggiornare gli indici.

Puoi evitare di creare indici esplosi evitando le query che richiederebbero un indice personalizzato utilizzando una proprietà elenco. Come descritto in precedenza, sono incluse le query con più ordini o query 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 la tua applicazione.

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

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 può 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 in corso...

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 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 utilizzare 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 dei predecessori o collection-group per gli indici non predecessori.