Entidades, propiedades y claves

Los objetos de datos en Cloud Datastore se conocen como entidades. Una entidad tiene una o más propiedades, que pueden tener uno o más valores. No es necesario que las entidades similares tengan las mismas propiedades y los valores de una entidad para una propiedad determinada no necesitan pertenecer al mismo tipo de datos. (Si fuera necesario, una aplicación puede establecer y aplicar estas restricciones en su propio modelo de datos).

Cloud Datastore es compatible con una variedad de tipos de datos para valores de propiedad. Se incluyen, entre otros:

  • Enteros
  • Números de coma flotante
  • Strings
  • Fechas
  • Datos binarios

Para obtener una lista completa de los tipos, consulta Tipos de valores y propiedades.

Cada entidad en Cloud Datastore tiene una clave que la identifica de manera única. La clave consta de los siguientes componentes:

  • El espacio de nombres de la entidad, que permite la función multiusuario
  • El tipo de entidad, que la clasifica con el propósito de realizar consultas de Cloud Datastore
  • Un identificador de la entidad individual, que puede ser una de las siguientes opciones:
    • una string de nombre de clave
    • un ID numérico de número entero
  • Una ruta de acceso principal opcional que ubica a la entidad dentro de la jerarquía de Cloud Datastore

Una aplicación puede recuperar una entidad individual de Cloud Datastore con su clave o puede recuperar una o más entidades mediante una consulta basada en los valores de propiedad o las claves de las entidades.

El SDK de Go en App Engine incluye un paquete para representar las entidades de Cloud Datastore como estructuras de Go, y para almacenarlas y recuperarlas en Cloud Datastore.

Cloud Datastore no aplica ninguna restricción en la estructura de las entidades; por ejemplo, si una propiedad posee un valor de un tipo en particular, esta tarea le corresponde a la aplicación.

Identificadores y tipos

Cada entidad de Cloud Datastore pertenece a un tipo en particular, que permite clasificar a la entidad con el propósito de realizar consultas. Por ejemplo, una aplicación de recursos humanos puede representar cada empleado de una empresa con una entidad del tipo Employee. En la API de Go Datastore, debes especificar un tipo de entidad cuando crees una datastore.Key. Todos los nombres de tipos que comienzan con dos guiones bajos (__) están reservados y no se pueden usar.

En el siguiente ejemplo, se crea una entidad del tipo Employee, se propagan sus valores de propiedad y se la guarda en Datastore:

import (
	"time"

	"golang.org/x/net/context"

	"google.golang.org/appengine/datastore"
)

type Employee struct {
	FirstName          string
	LastName           string
	HireDate           time.Time
	AttendedHRTraining bool
}

func f(ctx context.Context) {
	// ...
	employee := &Employee{
		FirstName: "Antonio",
		LastName:  "Salieri",
		HireDate:  time.Now(),
	}
	employee.AttendedHRTraining = true

	key := datastore.NewIncompleteKey(ctx, "Employee", nil)
	if _, err := datastore.Put(ctx, key, employee); err != nil {
		// Handle err
	}
	// ...
}

El tipo Employee declara cuatro campos para el modelo de datos: FirstName, LastName, HireDate y AttendedHRTraining.

Además de un tipo, cada entidad posee un identificador, que se asigna cuando se crea la entidad. Debido a que es parte de la clave de la entidad, el identificador se encuentra asociado de forma permanente a la entidad y no se puede cambiar. Se puede asignar de dos maneras:

  • Tu aplicación puede especificar su propia string de nombre de clave para la entidad.
  • Puedes hacer que Cloud Datastore le asigne un ID de número entero a la entidad de forma automática.

Para asignar un nombre de clave a la entidad, proporciona un argumento stringID que no esté vacío a datastore.NewKey:

// Create a key with a key name "asalieri".
key := datastore.NewKey(
	ctx,        // context.Context
	"Employee", // Kind
	"asalieri", // String ID; empty means no string ID
	0,          // Integer ID; if 0, generate automatically. Ignored if string ID specified.
	nil,        // Parent Key; nil means no parent
)

Para hacer que Cloud Datastore asigne un ID numérico automáticamente, utiliza un argumento stringID vacío:

// Create a key such as Employee:8261.
key := datastore.NewKey(ctx, "Employee", "", 0, nil)
// This is equivalent:
key = datastore.NewIncompleteKey(ctx, "Employee", nil)

Asignar identificadores

Cloud Datastore se puede configurar para generar ID automáticamente mediante dos políticas de identificación automática diferentes:

  • La política default genera una secuencia aleatoria de ID sin usar con una distribución aproximadamente uniforme. Cada ID puede tener hasta 16 dígitos.
  • La política legacy crea una secuencia de ID no consecutivos más breves compuestos por números enteros.

Si deseas mostrar los ID de las entidades a los usuarios o depender de que los soliciten, lo más recomendable es que uses la asignación manual.

Cloud Datastore genera una secuencia aleatoria de ID sin usar con una distribución aproximadamente uniforme. Cada ID puede tener hasta 16 dígitos.

Se garantiza que los valores de ID asignados por el sistema son siempre únicos para el grupo de entidad. Si copias una entidad desde un grupo de entidad o un espacio de nombres a otro y quieres conservar la parte de la clave que contiene el ID, asegúrate de asignar primero el ID a fin de evitar que Cloud Datastore seleccione ese ID para una asignación futura.

Rutas principales

Las entidades de Cloud Datastore conforman un espacio con estructura jerárquica, similar a la estructura de directorios de un sistema de archivos. Cuando creas una entidad, tienes la opción de designar otra entidad como su superior, en cuyo caso la nueva entidad es secundaria de la entidad principal (ten en cuenta que, a diferencia de lo que ocurre en un sistema de archivos, no es necesario que la entidad principal exista realmente). Las entidades que no tienen un superior se denominan entidades raíz. La asociación entre una entidad y su superior es permanente y no puede cambiarse una vez creada la entidad. Cloud Datastore nunca asignará el mismo ID numérico a dos entidades con el mismo superior ni a dos entidades raíz (que no tienen un superior).

El superior de una entidad, el superior de su superior y así sucesivamente son sus principales. Sus secundarios, los secundarios de sus secundarios y así sucesivamente son sus descendientes. Una entidad raíz y todos sus descendientes pertenecen al mismo grupo de entidad. La secuencia de entidades que comienza con una entidad raíz y sigue de superior a secundario, hasta llegar a determinada entidad, constituye la ruta de principales de esa entidad. La clave completa que identifica a una entidad consta de una secuencia de pares de grupo de similares-identificador que especifican su ruta de principales y terminan con la entidad en sí:

[Person:GreatGrandpa, Person:Grandpa, Person:Dad, Person:Me]

En el caso de una entidad raíz, la ruta principal está vacía, y la clave consta solo del grupo de similares y del identificador de la entidad:

[Person:GreatGrandpa]

Este concepto se ilustra en el diagrama que figura a continuación:

Muestra la relación de la entidad raíz con las entidades secundarias del grupo de entidad

Para designar el superior de una entidad, usa el argumento parent en datastore.NewKey. El valor de este argumento debería ser la clave de la entidad principal. En el siguiente ejemplo, se crea una entidad del tipo Address y se designa una entidad Employee como su superior:

// Create Employee entity
employee := &Employee{ /* ... */ }
employeeKey, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Employee", nil), employee)

// Use Employee as Address entity's parent
// and save Address entity to datastore
address := &Address{ /* ... */ }
addressKey := datastore.NewIncompleteKey(ctx, "Address", employeeKey)
_, err = datastore.Put(ctx, addressKey, address)

Transacciones y grupos de entidad

Cada intento de crear, actualizar o borrar una entidad ocurre en el contexto de una transacción. Una transacción puede incluir una cantidad indeterminada de las operaciones mencionadas. Para mantener la coherencia de los datos, la transacción garantiza que todas las operaciones que contiene se apliquen a Cloud Datastore como una unidad o que, si alguna de las operaciones falla, no se aplique ninguna de ellas. Además, todas las lecturas de coherencia sólida (consultas principales o captaciones) que se realizan dentro de la misma transacción ven una sola instantánea coherente de los datos.

Como se mencionó antes, un grupo de entidad es un conjunto de entidades conectadas de manera ascendente a un elemento raíz común. La organización de los datos en grupos de entidad puede limitar las transacciones que se pueden realizar:

  • Todos los datos a los que accede una transacción deben estar contenidos en 25 grupos de entidad como máximo.
  • Si quieres usar consultas dentro de una transacción, los datos deben estar organizados en grupos de entidad de manera tal que puedas especificar los filtros principales que coincidan con los datos correctos.
  • Existe un límite de capacidad de procesamiento de alrededor de una transacción por segundo dentro de un solo grupo de entidad. Esta limitación existe debido a que Cloud Datastore realiza una replicación síncrona y sin instancia maestra de cada grupo de entidad en una zona geográfica amplia para brindar alta confiabilidad y tolerancia a errores.

En un gran número de aplicaciones, es aceptable usar coherencia eventual (en otras palabras, consultas no principales que abarcan varios grupos de entidad, que algunas veces pueden mostrar datos inactivos) cuando se obtiene una visualización amplia de datos no relacionados y, luego, usar coherencia sólida (una consulta de entidad principal, o un get de una sola entidad) cuando se visualiza o edita un solo conjunto de datos altamente relacionados. En tales aplicaciones, suele ser una buena estrategia usar un grupo de entidad separado para cada conjunto de datos altamente relacionados. Para obtener más información, consulta Estructuración para coherencia sólida.

Tipos de valores y propiedades

Los valores de datos asociados con una entidad constan de una o más propiedades. Cada propiedad tiene un nombre y uno o más valores. Una propiedad puede tener valores de más de un tipo, y dos entidades pueden tener valores de diferentes tipos para la misma propiedad. Las propiedades pueden estar indexadas o no (las consultas que ordenan o filtran en una propiedad P ignorarán las entidades en las que P no está indexada). Una entidad puede tener como máximo 20,000 propiedades indexadas.

Se admiten los tipos de valor siguientes:

Tipo de valor Tipos de Go Orden Notas
Número entero int
int8
int16
int32
int64
Numérico Número entero de 64 bits, con firma
Número de coma flotante float32
float64
Numérico Doble precisión de 64 bits,
IEEE 754
Booleano bool false<true
String (corta) string Unicode
Hasta 1,500 bytes. Los valores más largos que 1,500 bytes dan como resultado un error en el entorno de ejecución.
String (larga) string (con noindex) Ninguno Hasta 1 megabyte

No indexado
Segmento de bytes (corto) datastore.ByteString Orden de bytes Hasta 1,500 bytes. Los valores más largos que 1,500 bytes dan como resultado un error en el entorno de ejecución.
Segmento de bytes (largo) []byte Ninguno Hasta 1 megabyte

No indexada
Fecha y hora time.Time Cronológico
Punto geográfico appengine.GeoPoint Por latitud,
luego, longitud
Clave de Cloud Datastore *datastore.Key Por elementos de ruta de acceso
(tipo, identificador,
similares, identificador…)
Clave de Blobstore appengine.BlobKey Orden de bytes

También se puede utilizar struct o slice para agregar propiedades. Consulta la referencia de Cloud Datastore para obtener más información.

Cuando una consulta incluye una propiedad con valores de varios tipos, Cloud Datastore usa un orden determinista basado en las representaciones internas.

  1. Valores nulos
  2. Números de coma fija
    • Números enteros
    • Fechas y horarios
  3. Valores booleanos
  4. secuencias de bytes
    • segmentos de bytes (cortos)
    • string de Unicode
    • Claves de Blobstore
  5. Números de coma flotante
  6. puntos geográficos
  7. claves de Cloud Datastore

Debido a que los segmentos de bytes largos y las strings largas no se indexan, no tienen un orden definido.

Trabajar con entidades

Las aplicaciones pueden utilizar la API de Cloud Datastore para crear, recuperar, actualizar y borrar entidades. Si la aplicación conoce la clave completa para una entidad (o si puede obtenerla de su tipo, identificador o clave superior), puede usar la clave para operar directamente en la entidad. Una aplicación también puede obtener la clave de una entidad como resultado de una consulta de Cloud Datastore; consulta la página Consultas de Datastore para obtener más información.

Crear una entidad

En Go, si quieres crear una entidad nueva, debes construir una instancia de una estructura de Go, propagar sus campos y llamar a datastore.Put para guardarla en Datastore. Solo los campos exportados (que empiecen con una letra mayúscula) se guardarán en Cloud Datastore. Para especificar el nombre de clave de la entidad, puedes pasar un argumento stringID que no esté vacío a datastore.NewKey:

employee := &Employee{
	FirstName: "Antonio",
	LastName:  "Salieri",
	HireDate:  time.Now(),
}
employee.AttendedHRTraining = true
key := datastore.NewKey(ctx, "Employee", "asalieri", 0, nil)
_, err = datastore.Put(ctx, key, employee)

Si proporcionas un nombre de clave vacío o usas datastore.NewIncompleteKey, Cloud Datastore generará de forma automática un ID numérico para la clave de la entidad:

employee := &Employee{
	FirstName: "Antonio",
	LastName:  "Salieri",
	HireDate:  time.Now(),
}
employee.AttendedHRTraining = true
key := datastore.NewIncompleteKey(ctx, "Employee", nil)
_, err = datastore.Put(ctx, key, employee)

Recuperar una entidad

Para recuperar una entidad identificada mediante una clave determinada, pasa la *datastore.Key como un argumento a la función datastore.Get. Puedes generar la *datastore.Key con la función datastore.NewKey.

employeeKey := datastore.NewKey(ctx, "Employee", "asalieri", 0, nil)
addressKey := datastore.NewKey(ctx, "Address", "", 1, employeeKey)
var addr Address
err = datastore.Get(ctx, addressKey, &addr)

La función datastore.Get propaga una instancia de la estructura de Go apropiada.

Actualizar una entidad

Para actualizar una entidad existente, modifica los atributos de la estructura y, luego, llama a datastore.Put. Los datos reemplazan la entidad existente. El objeto entero se envía a Cloud Datastore con cada llamada a datastore.Put.

Borrar una entidad

Si ya tienes la clave correspondiente, puedes borrar la entidad con la función datastore.Delete:

key := datastore.NewKey(ctx, "Employee", "asalieri", 0, nil)
err = datastore.Delete(ctx, key)

Operaciones por lotes

datastore.Put, datastore.Get y datastore.Delete tienen variantes por lotes denominadas datastore.PutMulti, datastore.GetMulti y datastore.DeleteMulti. Permiten actuar en múltiples entidades en una sola llamada a Cloud Datastore:

// A batch put.
_, err = datastore.PutMulti(ctx, []*datastore.Key{k1, k2, k3}, []interface{}{e1, e2, e3})

// A batch get.
var entities = make([]*T, 3)
err = datastore.GetMulti(ctx, []*datastore.Key{k1, k2, k3}, entities)

// A batch delete.
err = datastore.DeleteMulti(ctx, []*datastore.Key{k1, k2, k3})

Las operaciones por lotes no afectan los costos. Se te cobrará por cada clave en una operación por lotes, independientemente de si la clave existe o no. El tamaño de las entidades involucradas en una operación no influye en el costo.

Usa una lista vacía

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Entorno estándar de App Engine para Go