As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
QLDBDriver Amazon para Python — Referência do livro de receitas
Importante
Aviso de fim do suporte: os clientes existentes poderão usar a Amazon QLDB até o final do suporte em 31/07/2025. Para obter mais detalhes, consulte Migrar um Amazon QLDB Ledger para o Amazon Aurora Postgre
Este guia de referência mostra casos de uso comuns do QLDB driver Amazon para Python. Ele fornece exemplos de código Python que demonstram como usar o driver para executar operações básicas de criação, leitura, atualização e exclusão (CRUD). Também inclui exemplos de código para processamento de dados do Amazon Ion. Além disso, este guia destaca as práticas recomendadas para tornar as transações idempotentes e implantar restrições de exclusividade.
nota
Quando aplicável, alguns casos de uso têm exemplos de código diferentes para cada versão principal compatível do QLDB driver para Python.
Importação do driver
O exemplo de código a seguir importa o driver.
nota
Este exemplo também importa o pacote Amazon Ion (amazon.ion.simpleion
). Você precisa desse pacote para processar dados de íons ao executar algumas operações de dados nesta referência. Para saber mais, consulte Como trabalhar com o Amazon Ion.
Instanciação do driver
O exemplo de código a seguir cria uma instância do driver que se conecta a um nome de ledger especificado usando as configurações padrão.
CRUDoperações
QLDBexecuta operações de criação, leitura, atualização e exclusão (CRUD) como parte de uma transação.
Atenção
Como prática recomendada, torne suas transações de gravação estritamente idempotentes.
Tornar as transações idempotentes
Recomendamos que você torne as transações de gravação idempotentes para evitar efeitos colaterais inesperados no caso de novas tentativas. Uma transação é idempotente se puder ser executada várias vezes e produzir resultados idênticos a cada vez.
Por exemplo, considere uma transação que insere um documento em uma tabela chamada Person
. A transação deve primeiro verificar se o documento já existe ou não na tabela. Sem essa verificação, a tabela pode acabar com documentos duplicados.
Suponha que a transação seja confirmada QLDB com sucesso no lado do servidor, mas o cliente expire enquanto espera por uma resposta. Se a transação não for idempotente, o mesmo documento poderá ser inserido mais de uma vez no caso de uma nova tentativa.
Usar índices para evitar varreduras completas da tabela
Também recomendamos executar instruções com uma cláusula de predicado WHERE
usando um operador de igualdade em um campo indexado ou em um ID de documento, por exemplo, WHERE indexedField = 123
ou WHERE indexedField IN (456, 789)
. Sem essa pesquisa indexada, é QLDB necessário fazer uma varredura da tabela, o que pode levar a tempos limite de transação ou conflitos otimistas de controle de simultaneidade (). OCC
Para obter mais informações sobre o OCC, consulte Modelo de QLDB concorrência da Amazon.
Transações criadas implicitamente
O método pyqldb.driver.qldb_driver.execute_lambdaExecutor
envolve uma transação criada implicitamente.
Você pode executar instruções na função do Lambda usando o método do executor da transação execute_statement
nota
O método execute_statement
suporta os tipos Amazon Ion e os tipos nativos do Python. Se você passar um tipo nativo do Python como argumento para execute_statement
, o driver o converterá em um tipo Ion usando o módulo amazon.ion.simpleion
(desde que a conversão para o determinado tipo de dados do Python seja suportada). Para ver os tipos de dados e as regras de conversão compatíveis, consulte o código-fonte simpleion
As seções a seguir mostram como executar CRUD operações básicas, especificar a lógica de repetição personalizada e implementar restrições de exclusividade.
Sumário
Criar tabelas
def create_table(transaction_executor): transaction_executor.execute_statement("CREATE TABLE Person") qldb_driver.execute_lambda(lambda executor: create_table(executor))
Criar índices
def create_index(transaction_executor): transaction_executor.execute_statement("CREATE INDEX ON Person(GovId)") qldb_driver.execute_lambda(lambda executor: create_index(executor))
Ler documentos
# Assumes that Person table has documents as follows: # { "GovId": "TOYENC486FH", "FirstName": "Brent" } def read_documents(transaction_executor): cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = 'TOYENC486FH'") for doc in cursor: print(doc["GovId"]) # prints TOYENC486FH print(doc["FirstName"]) # prints Brent qldb_driver.execute_lambda(lambda executor: read_documents(executor))
Usar parâmetros de consulta
O exemplo de código a seguir usa um parâmetro de consulta do tipo nativo.
cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ?", 'TOYENC486FH')
O exemplo de código a seguir usa um parâmetro de consulta do tipo Ion.
name = ion.loads('Brent') cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE FirstName = ?", name)
O exemplo de código a seguir usa múltiplos parâmetros de consulta.
cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ? AND FirstName = ?", 'TOYENC486FH', "Brent")
O exemplo de código a seguir usa uma lista de parâmetros de consulta.
gov_ids = ['TOYENC486FH','ROEE1','YH844'] cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId IN (?,?,?)", *gov_ids)
nota
Quando você executa uma consulta sem uma pesquisa indexada, ela invoca uma verificação completa da tabela. Neste exemplo, recomendamos ter um índice no campo GovId
para otimizar o desempenho. Sem um índice ativadoGovId
, as consultas podem ter mais latência e também podem levar a exceções de OCC conflito ou tempos limite de transação.
Inserir documentos
Os exemplos de código a seguir inserem os tipos de dados nativos.
def insert_documents(transaction_executor, arg_1): # Check if doc with GovId:TOYENC486FH exists # This is critical to make this transaction idempotent cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ?", 'TOYENC486FH') # Check if there is any record in the cursor first_record = next(cursor, None) if first_record: # Record already exists, no need to insert pass else: transaction_executor.execute_statement("INSERT INTO Person ?", arg_1) doc_1 = { 'FirstName': "Brent", 'GovId': 'TOYENC486FH', } qldb_driver.execute_lambda(lambda executor: insert_documents(executor, doc_1))
Os exemplos de código a seguir inserem os tipos de dados Ion.
def insert_documents(transaction_executor, arg_1): # Check if doc with GovId:TOYENC486FH exists # This is critical to make this transaction idempotent cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ?", 'TOYENC486FH') # Check if there is any record in the cursor first_record = next(cursor, None) if first_record: # Record already exists, no need to insert pass else: transaction_executor.execute_statement("INSERT INTO Person ?", arg_1) doc_1 = { 'FirstName': 'Brent', 'GovId': 'TOYENC486FH', } # create a sample Ion doc ion_doc_1 = simpleion.loads(simpleion.dumps(doc_1))) qldb_driver.execute_lambda(lambda executor: insert_documents(executor, ion_doc_1))
Essa transação insere um documento na tabela Person
. Antes de inserir, ele primeiro verifica se o documento já existe na tabela. Essa verificação torna a transação idempotente por natureza. Mesmo que você execute essa transação várias vezes, ela não causará efeitos colaterais indesejados.
nota
Neste exemplo, recomendamos ter um índice no campo GovId
para otimizar o desempenho. Sem um índice ativadoGovId
, as declarações podem ter mais latência e também podem levar a exceções de OCC conflito ou tempos limite de transação.
Inserindo vários documentos em uma instrução
Para inserir vários documentos usando uma única instrução INSERT, você pode passar um parâmetro do tipo lista para a instrução da seguinte maneira.
# people is a list transaction_executor.execute_statement("INSERT INTO Person ?", people)
Você não coloca o marcador variável (?
) entre colchetes angulares duplos (<<...>>
) ao passar uma lista. Nas instruções manuais do PartiQL, colchetes angulares duplos denotam uma coleção não ordenada conhecida como bolsa.
Como atualizar documentos
Os exemplos de código a seguir usam tipos de dados nativos.
def update_documents(transaction_executor, gov_id, name): transaction_executor.execute_statement("UPDATE Person SET FirstName = ? WHERE GovId = ?", name, gov_id) gov_id = 'TOYENC486FH' name = 'John' qldb_driver.execute_lambda(lambda executor: update_documents(executor, gov_id, name))
O exemplo de código a seguir usa os tipos de dados Ion.
def update_documents(transaction_executor, gov_id, name): transaction_executor.execute_statement("UPDATE Person SET FirstName = ? WHERE GovId = ?", name, gov_id) # Ion datatypes gov_id = simpleion.loads('TOYENC486FH') name = simpleion.loads('John') qldb_driver.execute_lambda(lambda executor: update_documents(executor, gov_id, name))
nota
Neste exemplo, recomendamos ter um índice no campo GovId
para otimizar o desempenho. Sem um índice ativadoGovId
, as declarações podem ter mais latência e também podem levar a exceções de OCC conflito ou tempos limite de transação.
Como excluir documentos
Os exemplos de código a seguir usam tipos de dados nativos.
def delete_documents(transaction_executor, gov_id): cursor = transaction_executor.execute_statement("DELETE FROM Person WHERE GovId = ?", gov_id) gov_id = 'TOYENC486FH' qldb_driver.execute_lambda(lambda executor: delete_documents(executor, gov_id))
O exemplo de código a seguir usa os tipos de dados Ion.
def delete_documents(transaction_executor, gov_id): cursor = transaction_executor.execute_statement("DELETE FROM Person WHERE GovId = ?", gov_id) # Ion datatypes gov_id = simpleion.loads('TOYENC486FH') qldb_driver.execute_lambda(lambda executor: delete_documents(executor, gov_id))
nota
Neste exemplo, recomendamos ter um índice no campo GovId
para otimizar o desempenho. Sem um índice ativadoGovId
, as declarações podem ter mais latência e também podem levar a exceções de OCC conflito ou tempos limite de transação.
Executando várias instruções em uma transação
# This code snippet is intentionally trivial. In reality you wouldn't do this because you'd # set your UPDATE to filter on vin and insured, and check if you updated something or not. def do_insure_car(transaction_executor, vin): cursor = transaction_executor.execute_statement( "SELECT insured FROM Vehicles WHERE vin = ? AND insured = FALSE", vin) first_record = next(cursor, None) if first_record: transaction_executor.execute_statement( "UPDATE Vehicles SET insured = TRUE WHERE vin = ?", vin) return True else: return False def insure_car(qldb_driver, vin_to_insure): return qldb_driver.execute_lambda( lambda executor: do_insure_car(executor, vin_to_insure))
Lógica de novas tentativas
O execute_lambda
método do driver tem um mecanismo de repetição integrado que repete a transação se ocorrer uma exceção que pode ser repetida (como tempos limite ou conflitos). OCC
Implementação de restrições de exclusividade
QLDBnão oferece suporte a índices exclusivos, mas você pode implementar esse comportamento em seu aplicativo.
Suponha que você queira implementar uma restrição de exclusividade no campo GovId
da tabela Person
. Para fazer isso, você pode escrever uma transação que faça o seguinte:
-
Afirme que a tabela não tem documentos existentes com um
GovId
especificado. -
Insira o documento se a afirmação for aprovada.
Se uma transação concorrente passar simultaneamente pela declaração, somente uma das transações será confirmada com sucesso. A outra transação falhará com uma exceção de OCC conflito.
O exemplo de código a seguir mostra como implementar essa lógica de restrição de exclusividade.
def insert_documents(transaction_executor, gov_id, document): # Check if doc with GovId = gov_id exists cursor = transaction_executor.execute_statement("SELECT * FROM Person WHERE GovId = ?", gov_id) # Check if there is any record in the cursor first_record = next(cursor, None) if first_record: # Record already exists, no need to insert pass else: transaction_executor.execute_statement("INSERT INTO Person ?", document) qldb_driver.execute_lambda(lambda executor: insert_documents(executor, gov_id, document))
nota
Neste exemplo, recomendamos ter um índice no campo GovId
para otimizar o desempenho. Sem um índice ativadoGovId
, as declarações podem ter mais latência e também podem levar a exceções de OCC conflito ou tempos limite de transação.
Como trabalhar com o Amazon Ion
As seções a seguir mostram como usar o módulo Amazon Ion para processar dados do Ion.
Sumário
Importar o módulo Ion
import amazon.ion.simpleion as simpleion
Criação de tipos de Ion
O exemplo de código a seguir cria um objeto Ion a partir do texto Ion.
ion_text = '{GovId: "TOYENC486FH", FirstName: "Brent"}' ion_obj = simpleion.loads(ion_text) print(ion_obj['GovId']) # prints TOYENC486FH print(ion_obj['Name']) # prints Brent
O exemplo de código a seguir cria um objeto Ion a partir de um dict
Python.
a_dict = { 'GovId': 'TOYENC486FH', 'FirstName': "Brent" } ion_obj = simpleion.loads(simpleion.dumps(a_dict)) print(ion_obj['GovId']) # prints TOYENC486FH print(ion_obj['FirstName']) # prints Brent
Obter um despejo de binário Ion
# ion_obj is an Ion struct print(simpleion.dumps(ion_obj)) # b'\xe0\x01\x00\xea\xee\x97\x81\x83\xde\x93\x87\xbe\x90\x85GovId\x89FirstName\xde\x94\x8a\x8bTOYENC486FH\x8b\x85Brent'
Obter um despejo de texto Ion
# ion_obj is an Ion struct print(simpleion.dumps(ion_obj, binary=False)) # prints $ion_1_0 {GovId:'TOYENC486FH',FirstName:"Brent"}
Para obter mais informações sobre como trabalhar com o Ion, consulte a documentação do Amazon Ion