Índices

Cada consulta de Firestore en modo Datastore calcula sus resultados mediante uno o varios índices, que contienen claves de entidad en una secuencia especificada por las propiedades del índice y, opcionalmente, los ancestros de la entidad. Los índices se actualizan para reflejar los cambios que la aplicación hace en sus entidades, de modo que los resultados correctos de todas las consultas estén disponibles sin necesidad de realizar más cálculos.

Hay dos tipos de índices:

Índices integrados
De forma predeterminada, una base de datos en el modo Datastore predefine automáticamente un índice para cada propiedad de cada tipo de entidad. Estos índices de una sola propiedad son adecuados para tipos de consultas sencillos.
Índices compuestos
Los índices compuestos indexan varios valores de propiedad por entidad indexada. Los índices compuestos admiten consultas complejas y se definen en un archivo de configuración de índice (index.yaml).

Los tipos de índices se explican con más detalle más adelante.

Definición y estructura de índices

Un índice se define en una lista de propiedades de un tipo de entidad determinado, con un orden correspondiente (ascendente o descendente) para cada propiedad. Para usarlo con consultas de ancestros, el índice también puede incluir opcionalmente los ancestros de una entidad.

Un índice contiene entradas de cada propiedad cuyo nombre se indica en la definición del índice. Cada entrada del índice representa una entidad que es un resultado potencial de las consultas basadas en el índice. Una entidad solo se incluye en el índice si tiene un valor indexado definido para cada propiedad utilizada en el índice. Si la definición del índice hace referencia a una propiedad para la que la entidad no tiene ningún valor, esa entidad no aparecerá en el índice y, por lo tanto, nunca se devolverá como resultado de ninguna consulta basada en el índice.

El índice compuesto se ordena primero por ancestro y, después, por los valores de las propiedades, en el orden especificado en la definición del índice. Con esta información, puedes crear el índice perfecto que permita realizar consultas eficientes.

Configuración de índices

Firestore en el modo de Datastore proporciona índices integrados o automáticos para las consultas de los siguientes tipos:

  • Consultas independientes del tipo que solo usan filtros de ancestro y de clave
  • Consultas que solo usan filtros de ancestro y de igualdad
  • Consultas que solo usan filtros de desigualdad (que se limitan a una sola propiedad)
  • Consultas que solo usan filtros de ancestro, filtros de igualdad en propiedades y filtros de desigualdad en claves
  • Consultas sin filtros y con un solo orden de clasificación en una propiedad, ya sea ascendente o descendente

Por ejemplo, de forma predeterminada, las bases de datos en modo Datastore predefinen automáticamente dos índices de una sola propiedad para cada propiedad de cada tipo de entidad: uno en orden ascendente y otro en orden descendente. Si no quieres que tu base de datos mantenga un índice de una propiedad, excluye la propiedad de tus índices. Ten en cuenta que, si excluyes una propiedad, se eliminará de todos los índices compuestos.

Los índices integrados son suficientes para realizar muchas consultas sencillas, como las que solo incluyen igualdades y las que incluyen desigualdades simples.

Los índices integrados no aparecen en la página Índices de la consola Google Cloud .

Para las consultas más complejas, una aplicación debe definir índices compuestos o manuales. Los índices compuestos son obligatorios para las consultas con el siguiente formato:

  • Consultas con filtros de ancestro y de desigualdad
  • Consultas con uno o varios filtros de desigualdad en una propiedad y uno o varios filtros de igualdad en otras propiedades
  • Consultas con un orden de clasificación de las claves en orden descendente
  • Consultas con varios criterios de ordenación
  • Consultas con uno o varios filtros y uno o varios criterios de ordenación

Los índices compuestos se definen en el archivo de configuración de índices de la aplicación (index.yaml). Los índices integrados no se incluyen en el archivo de configuración de índices.

Los índices compuestos se componen de varias propiedades y requieren que cada propiedad individual no se excluya de los índices.

Los índices compuestos se pueden ver en la página Índices de la Google Cloud consola. No puedes usar la consola de Google Cloud para crear ni actualizar índices compuestos.

Si la aplicación intenta realizar una consulta que no se puede ejecutar con los índices disponibles (ya sean integrados o especificados en el archivo de configuración de índice), la consulta fallará.

La API del modo Datastore sugiere automáticamente los índices que son adecuados para la mayoría de las aplicaciones. En función del uso que haga tu aplicación de tu base de datos del modo de Datastore, así como del tamaño y la forma de tus datos, puede que sea necesario ajustar los índices manualmente. Por ejemplo, escribir entidades con varios valores de propiedad puede dar lugar a un índice explosivo con costes de almacenamiento elevados y una mayor latencia de escritura.

El emulador de Datastore puede ayudarte a gestionar más fácilmente tu archivo de configuración de índices. En lugar de no ejecutar una consulta que requiere un índice y no lo tiene, el emulador de Datastore puede generar una configuración de índice que permita que la consulta se realice correctamente. Si la prueba local de una aplicación ejecuta todas las consultas posibles que emitirá la aplicación, usando todas las combinaciones de filtros y órdenes de clasificación, las entradas generadas representarán un conjunto completo de índices. Si las pruebas no abarcan todas las formas de consulta posibles, puedes revisar y ajustar el archivo de configuración del índice antes de actualizar los índices.

Puedes consultar más información sobre index.yaml en Configuración de índice.

Implementar o eliminar índices

Cuando hayas terminado de modificar el archivo de configuración del índice, ejecuta el comando gcloud datastore indexes create para poner los índices en servicio. Consulta más información sobre cómo actualizar tus índices.

Si has desplegado índices que ya no necesitas, puedes eliminarlos.

Costes de almacenamiento y latencia de escritura

Los índices contribuyen a los costes de almacenamiento. En Tamaño de entrada de índice se describe cómo contribuyen los índices compuestos y los integrados al tamaño de almacenamiento de tu base de datos. Puedes usar las estadísticas de Firestore en modo Datastore para ver más información sobre las entradas de índice y el tamaño de almacenamiento de los índices.

Los índices también contribuyen a la latencia de escritura. Al actualizar el valor de una propiedad, la base de datos también actualiza todos los índices relacionados. Cuantos más índices tenga que actualizar la base de datos, más tardará la operación.

Puede reducir los costes de almacenamiento y mejorar el rendimiento de escritura eliminando los índices no utilizados y excluyendo propiedades de la indexación. De esta forma, también se evitan errores en las operaciones debido a los límites de índice.

Índices y propiedades

A continuación, te indicamos algunos aspectos especiales que debes tener en cuenta sobre los índices y su relación con las propiedades de tus entidades:

Propiedades con tipos de valor mixtos

Cuando dos entidades tienen propiedades con el mismo nombre, pero con tipos de valor diferentes, un índice de la propiedad ordena las entidades primero por tipo de valor y, después, por un orden secundario adecuado para cada tipo. Por ejemplo, si dos entidades tienen una propiedad llamada age, una con un valor entero y otra con un valor de cadena, la entidad con el valor entero siempre precede a la que tiene el valor de cadena cuando se ordenan por la propiedad age, independientemente de los valores de las propiedades.

Esto es especialmente importante en el caso de los números enteros y los números de coma flotante, que se tratan como tipos independientes en el modo Datastore. Como todos los números enteros se ordenan antes que todos los números de coma flotante, una propiedad con el valor entero 38 se ordena antes que una con el valor de coma flotante 37.5.

Propiedades excluidas

Si sabes que nunca tendrás que filtrar ni ordenar por una propiedad concreta, puedes indicar a tu base de datos en el modo Datastore que no mantenga entradas de índice para esa propiedad excluyéndola de los índices. De esta forma, se reduce el coste de ejecutar la aplicación, ya que se disminuye el tamaño de almacenamiento necesario para las entradas de índice. Esto también puede mejorar la latencia de escritura. Una entidad con una propiedad excluida se comporta como si la propiedad no se hubiera definido: las consultas con un filtro o un orden de clasificación en la propiedad excluida nunca coincidirán con esa entidad.

La propiedad description del siguiente ejemplo se excluye de los índices:

C#

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API C# de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Go de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Java de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Node.js de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API PHP de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Python

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Python de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Ruby de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

No aplicable

La consulta del siguiente ejemplo no devolverá ningún resultado si se excluye la propiedad description:

C#

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API C# de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Go

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Go de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Java

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Java de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Node.js

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Node.js de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

PHP

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API PHP de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Python

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Python de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Ruby de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

GQL

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

Puede volver a cambiar la propiedad a indexada más adelante.

Sin embargo, ten en cuenta que, si cambias una propiedad de excluida a indexada, no se verán afectadas las entidades que se hayan creado antes del cambio. Las consultas que filtren por la propiedad no devolverán esas entidades, ya que no se escribieron en el índice de la consulta cuando se crearon. Para que las entidades sean accesibles en consultas futuras, debes volver a escribirlas en tu base de datos para que se introduzcan en los índices adecuados. Es decir, debes hacer lo siguiente con cada entidad de este tipo:

  1. Buscar (obtener) la entidad.
  2. Escribe (coloca) la entidad en tu base de datos.

Del mismo modo, si cambia una propiedad de indexada a excluida, solo se verán afectadas las entidades que se escriban posteriormente en su base de datos. Las entradas de índice de las entidades que ya tengan esa propiedad seguirán existiendo hasta que se actualicen o se eliminen. Para evitar resultados no deseados, debe eliminar de su código todas las consultas que filtren u ordenen por la propiedad (ahora excluida).

Límites de los índices

Firestore en modo Datastore impone límites en el número y el tamaño total de las entradas de índice que se pueden asociar a una sola entidad. Estos límites son elevados y la mayoría de las aplicaciones no se ven afectadas. Sin embargo, hay circunstancias en las que puedes alcanzar los límites.

Como se ha descrito más arriba, una base de datos en el modo Datastore crea una entrada en un índice predefinido para cada propiedad de cada entidad, excepto para las que hayas declarado explícitamente como excluidas de tus índices. La propiedad también se puede incluir en índices personalizados adicionales declarados en el archivo de configuración de índice (index.yaml). Siempre que una entidad no tenga propiedades de lista, tendrá como máximo una entrada en cada índice personalizado (en el caso de los índices que no son de ancestros) o una por cada uno de los ancestros de la entidad (en el caso de los índices de ancestros). Cada una de estas entradas de índice debe actualizarse cada vez que cambie el valor de la propiedad.

En el caso de una propiedad que tiene un solo valor para cada entidad, cada valor posible debe almacenarse solo una vez por entidad en el índice predefinido de la propiedad. Aun así, es posible que una entidad con un gran número de propiedades de un solo valor supere el límite de entrada o de tamaño del índice. Del mismo modo, una entidad que puede tener varios valores para la misma propiedad requiere una entrada de índice independiente para cada valor. De nuevo, si el número de valores posibles es grande, dicha entidad puede superar el límite de entradas.

La situación empeora en el caso de las entidades con varias propiedades, cada una de las cuales puede adoptar varios valores. Para dar cabida a una entidad de este tipo, el índice debe incluir una entrada para cada combinación posible de valores de propiedad. Los índices personalizados que hacen referencia a varias propiedades, cada una con varios valores, pueden "explotar" combinatoriamente, lo que requiere un gran número de entradas para una entidad con un número relativamente pequeño de valores de propiedad posibles. Estos índices explosivos pueden aumentar considerablemente el tamaño de almacenamiento de una entidad debido al gran número de entradas de índice que se deben almacenar. Los índices explosivos también pueden provocar que la entidad supere el límite de recuento o de tamaño de las entradas de índice.

Echa un vistazo al siguiente código:

C#

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API C# de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Go de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Java

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Java de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Node.js

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Node.js de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

PHP

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API PHP de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Python

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Python de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

Para saber cómo instalar y usar la biblioteca de cliente de Cloud Datastore, consulta las bibliotecas de cliente de Cloud Datastore. Para obtener más información, consulta la documentación de referencia de la API Ruby de Cloud Datastore.

Para autenticarte en Cloud Datastore, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

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

GQL

No aplicable

Crea una entidad Task con tres valores para la propiedad tags, tres valores para la propiedad collaborators y created con la fecha actual. Esto requerirá 9 entradas de índice, una por cada combinación posible de valores de propiedad:

('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())

Cuando la misma propiedad se repite varias veces, Firestore en modo Datastore puede detectar índices explosivos y sugerir un índice alternativo. Sin embargo, en todas las demás circunstancias (como la consulta definida en este ejemplo), una base de datos en modo Datastore generará un índice explosivo. En este caso, puedes evitar que el índice se descomponga configurando manualmente un índice en el archivo de configuración de índices:

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

De esta forma, solo se necesitan (|tags| * |created| + |collaborators| * |created|) entradas, es decir, 6 en lugar de 9:

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

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

Cualquier operación commit que provoque que un índice supere el límite de entrada o de tamaño del índice fallará. En el texto del error se describe qué límite se ha superado ("Too many indexed properties" o "Index entries too large") y qué índice personalizado ha provocado el error. Si creas un índice que supere los límites de cualquier entidad cuando se compile, las consultas en el índice fallarán y el índice aparecerá en el estado Error en la consola Google Cloud . Para gestionar estos índices Error,

  1. Quita el índice del archivo de configuración del índice (index.yaml).
  2. Con Google Cloud CLI, elimina el índice de la base de datos mediante el comando datastore indexes cleanup, tal como se describe en Eliminar índices no utilizados.
  3. Alternativas:
    • Reformular la definición del índice y las consultas correspondientes.
    • eliminar las entidades que provocan que el índice se desborde.
  4. Vuelve a añadir el índice a index.yaml.
  5. Con la CLI de Google Cloud, añade el índice a la base de datos ejecutando el comando datastore indexes create, tal como se describe en Actualizar índices.

Si no quieres que un índice se amplíe, evita las consultas que requieran un índice personalizado mediante el uso de una propiedad de lista. Como se ha descrito anteriormente, esto incluye las consultas con varios criterios de ordenación o con una combinación de filtros de igualdad y desigualdad.

Índices de proyecciones

Las consultas de proyección requieren que todas las propiedades especificadas en la proyección se incluyan en un índice. El emulador de Datastore genera automáticamente los índices necesarios en el archivo de configuración de índices, index.yaml, que se sube con tu aplicación.

Una forma de minimizar el número de índices necesarios es proyectar las mismas propiedades de forma coherente, aunque no siempre sean necesarias. Por ejemplo, estas consultas requieren dos índices independientes:

SELECT priority, percent_complete FROM Task

SELECT priority, percent_complete, created FROM Task

Sin embargo, si siempre proyectas las propiedades priority, percent_complete y created, aunque no sea necesario created, solo se necesitará un índice.

Para convertir una consulta en una consulta de proyección, puede que tengas que crear un índice si las propiedades de la proyección no están incluidas en otra parte de la consulta. Por ejemplo, supongamos que tienes una consulta como la siguiente:

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

que requiere el índice:

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

Convertir esta consulta en cualquiera de las consultas de proyección

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 nueva propiedad (created) y, por lo tanto, requiere crear un nuevo índice:

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

Sin embargo,

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

no cambiaría el índice necesario, ya que las propiedades proyectadas priority y percent_complete ya se incluían en la consulta.

Varias bases de datos

Puedes usar gcloud firestore para gestionar un solo índice del modo Datastore o usar gcloud datastore con un archivo index.yaml para gestionar todos los índices de una base de datos.

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

Haz los cambios siguientes:

  • DATABASE_ID: un ID de base de datos.
  • QUERY_SCOPE: puede ser collection-recursive para los índices de ancestros o collection-group para los índices que no son de ancestros.