Controlador Amazon QLDB para Go: tutorial de inicio rápido - Amazon Quantum Ledger Database (Amazon QLDB)

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Controlador Amazon QLDB para Go: tutorial de inicio rápido

En este tutorial aprenderá a configurar una aplicación sencilla con la última versión del controlador Amazon QLDB para Go. En esta guía se incluyen los pasos para instalar el controlador y ejemplos de código breve de las operaciones básicas de creación, lectura, actualización y eliminación (CRUD).

Requisitos previos

Antes de comenzar, asegúrese de que hace lo siguiente:

  1. Si aún no lo ha hecho, complete el Requisitos previos para el controlador Go. Deberá registrarse en AWS, conceder acceso programático de desarrollo e instalar Go.

  2. Cree un libro mayor denominado quick-start.

    Para obtener más información sobre cómo crear un libro mayor, consulte Operaciones básicas de libros mayores de Amazon QLDB o Paso 1: crear un nuevo libro mayor en Introducción a la consola.

Paso 1: instalar el controlador

Asegúrese de que su proyecto utilice los módulos de Go para instalar las dependencias del proyecto.

Ejecute el siguiente comando go get en el directorio de su proyecto.

$ go get -u github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver

Al instalar el controlador también se instalan sus dependencias, incluidos AWS SDK for Go v2 y los paquetes de Amazon Ion.

Paso 2: importar los paquetes

Importe los siguientes paquetes AWS.

import ( "context" "fmt" "github.com/amzn/ion-go/ion" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/qldbSession" "github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver" )

Paso 3: inicializar el controlador

Inicialice una instancia del controlador que se conecte al libro mayor denominado quick-start.

cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { panic(err) } qldbSession := qldbsession.NewFromConfig(cfg, func(options *qldbsession.Options) { options.Region = "us-east-1" }) driver, err := qldbdriver.New( "quick-start", qldbSession, func(options *qldbdriver.DriverOptions) { options.LoggerVerbosity = qldbdriver.LogInfo }) if err != nil { panic(err) } defer driver.Shutdown(context.Background())
nota

En este ejemplo de código, sustituya us-east-1 por el Región de AWS donde creó el libro mayor.

Paso 4: crear una tabla y un índice

Los siguientes ejemplos de código muestran cómo ejecutar las instrucciones CREATE TABLE y CREATE INDEX.

_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { _, err := txn.Execute("CREATE TABLE People") if err != nil { return nil, err } // When working with QLDB, it's recommended to create an index on fields we're filtering on. // This reduces the chance of OCC conflict exceptions with large datasets. _, err = txn.Execute("CREATE INDEX ON People (firstName)") if err != nil { return nil, err } _, err = txn.Execute("CREATE INDEX ON People (age)") if err != nil { return nil, err } return nil, nil }) if err != nil { panic(err) }

Este código crea una tabla con el nombre People y los índices de los campos firstName y age de esa tabla. Los índices son necesarios para optimizar el rendimiento de las consultas y ayudar a limitar las excepciones de conflicto de control de concurrencia optimista (OCC).

Paso 5: insertar un documento

El siguiente ejemplo de código muestra cómo ejecutar la instrucción INSERT. QLDB es compatible con el lenguaje de consultas PartiQL (compatible con SQL) y el formato de datos Amazon Ion (superconjunto de JSON).

Uso de literales PartiQL

El siguiente código inserta un documento en la tabla People mediante una instrucción PartiQL de literal de cadena.

_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("INSERT INTO People {'firstName': 'Jane', 'lastName': 'Doe', 'age': 77}") }) if err != nil { panic(err) }

Uso de tipos de datos de Ion

De forma similar al paquete JSON integrado en Go, puede serializar y anular la serialización de los tipos de datos de Go desde y hacia Ion.

  1. Suponga que tiene la siguiente estructura de Go denominada Person.

    type Person struct { FirstName string `ion:"firstName"` LastName string `ion:"lastName"` Age int `ion:"age"` }
  2. Cree una instancia de Person.

    person := Person{"John", "Doe", 54}

    El controlador serializa automáticamente una representación de texto codificada en Ion de person.

    importante

    Para que la serialización y la anulación de la serialización funcionen correctamente, se deben exportar los nombres de campo de la estructura de datos de Go (primera letra en mayúscula).

  3. Pase la instancia person al método Execute de la transacción.

    _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("INSERT INTO People ?", person) }) if err != nil { panic(err) }

    En este ejemplo se emplea un signo de interrogación (?) como marcador de posición variable para pasar la información del documento a la instrucción. Al utilizar marcadores de posición, debe pasar un valor de texto codificado por Ion.

    sugerencia

    Para insertar varios documentos mediante una sola instrucción INSERT, puede pasar un parámetro del tipo list a la instrucción de la siguiente manera.

    // people is a list txn.Execute("INSERT INTO People ?", people)

    No coloque el marcador de posición variable (?) entre corchetes de doble ángulo (<<...>>) al pasar una lista. En las instrucciones PartiQL manuales, los corchetes de doble ángulo indican una colección desordenada conocida como bolsa.

Paso 6: consulta del documento

El siguiente ejemplo de código muestra cómo ejecutar una instrucción SELECT.

p, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE age = 54") if err != nil { return nil, err } // Assume the result is not empty hasNext := result.Next(txn) if !hasNext && result.Err() != nil { return nil, result.Err() } ionBinary := result.GetCurrentData() temp := new(Person) err = ion.Unmarshal(ionBinary, temp) if err != nil { return nil, err } return *temp, nil }) if err != nil { panic(err) } var returnedPerson Person returnedPerson = p.(Person) if returnedPerson != person { fmt.Print("Queried result does not match inserted struct") }

En este ejemplo, se consulta el documento desde la tabla People, se supone que el conjunto de resultados no está vacío y se devuelve el documento a partir del resultado.

Paso 7: actualizar el documento

El siguiente ejemplo de código muestra cómo ejecutar a instrucción UPDATE.

person.Age += 10 _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("UPDATE People SET age = ? WHERE firstName = ?", person.Age, person.FirstName) }) if err != nil { panic(err) }

Paso 8: consulta al documento actualizado

El siguiente ejemplo de código consulta la tabla People mediante firstName y devuelve todos los documentos del conjunto de resultados.

p, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE firstName = ?", person.FirstName) if err != nil { return nil, err } var people []Person for result.Next(txn) { ionBinary := result.GetCurrentData() temp := new(Person) err = ion.Unmarshal(ionBinary, temp) if err != nil { return nil, err } people = append(people, *temp) } if result.Err() != nil { return nil, result.Err() } return people, nil }) if err != nil { panic(err) } var people []Person people = p.([]Person) updatedPerson := Person{"John", "Doe", 64} if people[0] != updatedPerson { fmt.Print("Queried result does not match updated struct") }

Paso 9: descarte de la tabla

El siguiente ejemplo de código muestra cómo ejecutar una instrucción DROP TABLE.

_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("DROP TABLE People") }) if err != nil { panic(err) }

Ejecución de la aplicación completa

El siguiente ejemplo de código es la versión completa de la aplicación. En lugar de seguir los pasos anteriores de forma individual, también puede copiar y ejecutar este ejemplo de código de principio a fin. Esta aplicación muestra algunas operaciones básicas de CRUD en el libro mayor denominado quick-start.

nota

Antes de ejecutar este código, asegúrese de no tener ya una tabla activa con el nombre People en el libro mayor quick-start.

package main import ( "context" "fmt" "github.com/amzn/ion-go/ion" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/qldbsession" "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver" ) func main() { awsSession := session.Must(session.NewSession(aws.NewConfig().WithRegion("us-east-1"))) qldbSession := qldbsession.New(awsSession) driver, err := qldbdriver.New( "quick-start", qldbSession, func(options *qldbdriver.DriverOptions) { options.LoggerVerbosity = qldbdriver.LogInfo }) if err != nil { panic(err) } defer driver.Shutdown(context.Background()) _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { _, err := txn.Execute("CREATE TABLE People") if err != nil { return nil, err } // When working with QLDB, it's recommended to create an index on fields we're filtering on. // This reduces the chance of OCC conflict exceptions with large datasets. _, err = txn.Execute("CREATE INDEX ON People (firstName)") if err != nil { return nil, err } _, err = txn.Execute("CREATE INDEX ON People (age)") if err != nil { return nil, err } return nil, nil }) if err != nil { panic(err) } _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("INSERT INTO People {'firstName': 'Jane', 'lastName': 'Doe', 'age': 77}") }) if err != nil { panic(err) } type Person struct { FirstName string `ion:"firstName"` LastName string `ion:"lastName"` Age int `ion:"age"` } person := Person{"John", "Doe", 54} _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("INSERT INTO People ?", person) }) if err != nil { panic(err) } p, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE age = 54") if err != nil { return nil, err } // Assume the result is not empty hasNext := result.Next(txn) if !hasNext && result.Err() != nil { return nil, result.Err() } ionBinary := result.GetCurrentData() temp := new(Person) err = ion.Unmarshal(ionBinary, temp) if err != nil { return nil, err } return *temp, nil }) if err != nil { panic(err) } var returnedPerson Person returnedPerson = p.(Person) if returnedPerson != person { fmt.Print("Queried result does not match inserted struct") } person.Age += 10 _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("UPDATE People SET age = ? WHERE firstName = ?", person.Age, person.FirstName) }) if err != nil { panic(err) } p, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE firstName = ?", person.FirstName) if err != nil { return nil, err } var people []Person for result.Next(txn) { ionBinary := result.GetCurrentData() temp := new(Person) err = ion.Unmarshal(ionBinary, temp) if err != nil { return nil, err } people = append(people, *temp) } if result.Err() != nil { return nil, result.Err() } return people, nil }) if err != nil { panic(err) } var people []Person people = p.([]Person) updatedPerson := Person{"John", "Doe", 64} if people[0] != updatedPerson { fmt.Print("Queried result does not match updated struct") } _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("DROP TABLE People") }) if err != nil { panic(err) } }