Consultas de proyección

La mayoría de las consultas de Datastore muestran entidades completas como resultado. Sin embargo, solo unas pocas propiedades de la entidad suelen ser relevantes para las aplicaciones. Las consultas de proyección te permiten hacer consultas en Datastore para aquellas propiedades específicas de una entidad que en verdad necesitas, con una latencia y un costo más bajos que si recuperas la entidad completa.

Las consultas de proyección son similares a las consultas de SQL que tienen la siguiente forma.

SELECT name, email, phone FROM CUSTOMER

Puedes usar todas las funciones de filtrado y clasificación disponibles para las consultas de entidades estándar, con las limitaciones que se describen a continuación. La consulta muestra resultados resumidos en los que solo se propagan las propiedades especificadas (name, email y phone en el ejemplo) con valores. Todas las demás propiedades no tienen datos.

Usa consultas de proyección en Go 1.11

Cuando preparas una Query, especifica una proyección mediante el método Project:

q := datastore.NewQuery("People").Project("FirstName", "LastName")

Los resultados de estas consultas se controlan igual que los de una consulta de entidades estándar: por ejemplo, mediante la iteración sobre los resultados.

Las consultas de ejemplo siguientes para las propiedades Title, ReadPath y DateWritten de todas las entradas EventLog, ordenadas de forma ascendente por DateWritten, y se escribe cada valor de la propiedad en el registro de la aplicación:

q := datastore.NewQuery("EventLog").
	Project("Title", "ReadPath", "DateWritten").
	Order("DateWritten")
t := q.Run(ctx)
for {
	var l EventLog
	_, err := t.Next(&l)
	if err == datastore.Done {
		break
	}
	if err != nil {
		log.Errorf(ctx, "Running query: %v", err)
		break
	}
	log.Infof(ctx, "Log record: %v, %v, %v", l.Title, l.ReadPath, l.DateWritten)
}

Agrupación(experimental)

Las consultas de proyección pueden usar el método Distinct para garantizar que solo los resultados únicos por completo se muestren en un conjunto de resultados. Esto solo mostrará el primer resultado de las entidades que tengan el mismo valor para las propiedades que se están proyectando.

q := datastore.NewQuery("Person").
	Project("LastName", "Height").Distinct().
	Filter("Height >", 20).
	Order("-Height").Order("LastName")

Límites de las proyecciones

Las consultas de proyección están sujetas a las limitaciones siguientes:

  • Solo se pueden proyectar propiedades indexadas.

    La proyección no admite propiedades que no estén indexadas, ya sea de forma explícita o implícita. Las strings con más de 1,500 bytes y los arreglos de bytes con más de 1,500 elementos no se indexan.

  • No se puede proyectar la misma propiedad más de una vez

  • No se pueden proyectar las propiedades mencionadas en un filtro de igualdad (=).

    Por ejemplo,

    SELECT A FROM kind WHERE B = 1
    

    Es una consulta válida, ya que la propiedad proyectada no se usa en el filtro de igualdad. También lo es la siguiente consulta:

    SELECT A FROM kind WHERE A > 1
    

    No es un filtro de igualdad. Sin embargo, la siguiente consulta no es válida:

    SELECT A FROM kind WHERE A = 1
    

    La propiedad proyectada se usa en un filtro de igualdad.

  • Los resultados que muestra una consulta de proyección no se deben volver a guardar en Datastore.

    Dado que la consulta muestra resultados que solo están propagados de forma parcial, estos no deben volver a escribirse en Datastore.

Proyecciones y propiedades con varios valores

La proyección de una propiedad con valores múltiples no propagará todos los valores para esa propiedad. En su lugar, se mostrará una entidad independiente para cada combinación única de valores proyectados que coincidan con la consulta. Por ejemplo, supón que tienes una entidad del tipo Foo con dos propiedades con valores múltiples, A y B:

entity := Foo{A: []int{1, 1, 2, 3}, B: []string{"x", "y", "x"}}

Entonces, la consulta de proyección

q := datastore.NewQuery("Foo").Project("A", "B").Filter("A <", 3)

mostrará cuatro entidades con las combinaciones de valores siguientes:

A = 1, B = 'x'
A = 1, B = 'y'
A = 2, B = 'x'
A = 2, B = 'y'

Ten en cuenta que, si una entidad tiene una propiedad de valores múltiples sin valores, no se incluirán entradas en el índice y no se mostrarán resultados para esa entidad a partir de una consulta de proyección que incluya esa propiedad.

Índices para proyecciones

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

Una manera de minimizar el número de índices requeridos es proyectar las mismas propiedades de forma coherente, incluso si no las necesitas todas siempre. Por ejemplo, estas consultas requieren dos índices separados:

SELECT A, B FROM Kind
SELECT A, B, C FROM Kind

Sin embargo, si siempre proyectas las propiedades A, B y C, incluso si no necesitas C, solo necesitarás un índice.

Convertir una consulta existente en una consulta de proyección puede requerir que se cree un índice nuevo si las propiedades de la proyección no están incluidas en otra parte de la consulta. Por ejemplo, supón que tienes una consulta existente como esta:

SELECT * FROM Kind WHERE A > 1 ORDER BY A, B

que requiere el índice

Index(Kind, A, B)

Convertir esto en cualquiera de estas consultas de proyección

SELECT C FROM Kind WHERE A > 1 ORDER BY A, B
SELECT A, B, C FROM Kind WHERE A > 1 ORDER BY A, B

ingresa una nueva propiedad (C) y, por lo tanto, requerirá la creación de un nuevo índice Index(Kind, A, B, C). Ten en cuenta que la consulta de proyección

SELECT A, B FROM Kind WHERE A > 1 ORDER BY A, B

no cambiaría el índice requerido, debido a que las propiedades proyectadas A y B ya estaban incluidas en la consulta existente.