ステップ 5: 台帳内のドキュメントを変更する - Amazon Quantum Ledger Database (Amazon QLDB)

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

ステップ 5: 台帳内のドキュメントを変更する

操作するデータを用意できたところで、Amazon QLDB で vehicle-registration 台帳のドキュメントに変更を加えることができます。このステップでは、次のコード例により、データ操作言語 (DML) ステートメントを実行する方法を示します。これらのステートメントは、ある車両の主所有者を更新し、別の車両に第二所有者を追加します。

ドキュメントに変更を加えるには
  1. 次のプログラム (TransferVehicleOwnership.ts) を使用して、台帳で VIN が 1N4AL11D75C109151 の車両の主所有者を更新します。

    /* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import { QldbDriver, Result, TransactionExecutor } from "amazon-qldb-driver-nodejs"; import { dom } from "ion-js"; import { getQldbDriver } from "./ConnectToLedger"; import { PERSON, VEHICLE } from "./model/SampleData"; import { PERSON_TABLE_NAME } from "./qldb/Constants"; import { error, log } from "./qldb/LogUtil"; import { getDocumentId } from "./qldb/Util"; /** * Query a driver's information using the given ID. * @param txn The {@linkcode TransactionExecutor} for lambda execute. * @param documentId The unique ID of a document in the Person table. * @returns Promise which fulfills with an Ion value containing the person. */ export async function findPersonFromDocumentId(txn: TransactionExecutor, documentId: string): Promise<dom.Value> { const query: string = "SELECT p.* FROM Person AS p BY pid WHERE pid = ?"; let personId: dom.Value; await txn.execute(query, documentId).then((result: Result) => { const resultList: dom.Value[] = result.getResultList(); if (resultList.length === 0) { throw new Error(`Unable to find person with ID: ${documentId}.`); } personId = resultList[0]; }); return personId; } /** * Find the primary owner for the given VIN. * @param txn The {@linkcode TransactionExecutor} for lambda execute. * @param vin The VIN to find primary owner for. * @returns Promise which fulfills with an Ion value containing the primary owner. */ export async function findPrimaryOwnerForVehicle(txn: TransactionExecutor, vin: string): Promise<dom.Value> { log(`Finding primary owner for vehicle with VIN: ${vin}`); const query: string = "SELECT Owners.PrimaryOwner.PersonId FROM VehicleRegistration AS v WHERE v.VIN = ?"; let documentId: string = undefined; await txn.execute(query, vin).then((result: Result) => { const resultList: dom.Value[] = result.getResultList(); if (resultList.length === 0) { throw new Error(`Unable to retrieve document ID using ${vin}.`); } const PersonIdValue: dom.Value = resultList[0].get("PersonId"); if (PersonIdValue === null) { throw new Error(`Expected field name PersonId not found.`); } documentId = PersonIdValue.stringValue(); }); return findPersonFromDocumentId(txn, documentId); } /** * Update the primary owner for a vehicle using the given VIN. * @param txn The {@linkcode TransactionExecutor} for lambda execute. * @param vin The VIN for the vehicle to operate on. * @param documentId New PersonId for the primary owner. * @returns Promise which fulfills with void. */ async function updateVehicleRegistration(txn: TransactionExecutor, vin: string, documentId: string): Promise<void> { const statement: string = "UPDATE VehicleRegistration AS r SET r.Owners.PrimaryOwner.PersonId = ? WHERE r.VIN = ?"; log(`Updating the primary owner for vehicle with VIN: ${vin}...`); await txn.execute(statement, documentId, vin).then((result: Result) => { const resultList: dom.Value[] = result.getResultList(); if (resultList.length === 0) { throw new Error("Unable to transfer vehicle, could not find registration."); } log(`Successfully transferred vehicle with VIN ${vin} to new owner.`); }); } /** * Validate the current owner of the given vehicle and transfer its ownership to a new owner in a single transaction. * @param txn The {@linkcode TransactionExecutor} for lambda execute. * @param vin The VIN of the vehicle to transfer ownership of. * @param currentOwner The GovId of the current owner of the vehicle. * @param newOwner The GovId of the new owner of the vehicle. */ export async function validateAndUpdateRegistration( txn: TransactionExecutor, vin: string, currentOwner: string, newOwner: string ): Promise<void> { const primaryOwner: dom.Value = await findPrimaryOwnerForVehicle(txn, vin); const govIdValue: dom.Value = primaryOwner.get("GovId"); if (govIdValue !== null && govIdValue.stringValue() !== currentOwner) { log("Incorrect primary owner identified for vehicle, unable to transfer."); } else { const documentId: string = await getDocumentId(txn, PERSON_TABLE_NAME, "GovId", newOwner); await updateVehicleRegistration(txn, vin, documentId); log("Successfully transferred vehicle ownership!"); } } /** * Find primary owner for a particular vehicle's VIN. * Transfer to another primary owner for a particular vehicle's VIN. * @returns Promise which fulfills with void. */ const main = async function(): Promise<void> { try { const qldbDriver: QldbDriver = getQldbDriver(); const vin: string = VEHICLE[0].VIN; const previousOwnerGovId: string = PERSON[0].GovId; const newPrimaryOwnerGovId: string = PERSON[1].GovId; await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { await validateAndUpdateRegistration(txn, vin, previousOwnerGovId, newPrimaryOwnerGovId); }); } catch (e) { error(`Unable to connect and run queries: ${e}`); } } if (require.main === module) { main(); }
  2. トランスパイルされたプログラムを実行するには、次のコマンドを入力します。

    node dist/TransferVehicleOwnership.js
  3. 次のプログラム (AddSecondaryOwner.ts) を使用して、台帳で VIN が KM8SRDHF6EU074761 の車両に第二所有者を追加します。

    /* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import { QldbDriver, Result, TransactionExecutor } from "amazon-qldb-driver-nodejs"; import { dom } from "ion-js"; import { getQldbDriver } from "./ConnectToLedger"; import { PERSON, VEHICLE_REGISTRATION } from "./model/SampleData"; import { PERSON_TABLE_NAME } from "./qldb/Constants"; import { error, log } from "./qldb/LogUtil"; import { getDocumentId } from "./qldb/Util"; import { prettyPrintResultList } from "./ScanTable"; /** * Add a secondary owner into 'VehicleRegistration' table for a particular VIN. * @param txn The {@linkcode TransactionExecutor} for lambda execute. * @param vin VIN of the vehicle to query. * @param secondaryOwnerId The secondary owner's person ID. * @returns Promise which fulfills with void. */ export async function addSecondaryOwner( txn: TransactionExecutor, vin: string, secondaryOwnerId: string ): Promise<void> { log(`Inserting secondary owner for vehicle with VIN: ${vin}`); const query: string = `FROM VehicleRegistration AS v WHERE v.VIN = ? INSERT INTO v.Owners.SecondaryOwners VALUE ?`; const personToInsert = {PersonId: secondaryOwnerId}; await txn.execute(query, vin, personToInsert).then(async (result: Result) => { const resultList: dom.Value[] = result.getResultList(); log("VehicleRegistration Document IDs which had secondary owners added: "); prettyPrintResultList(resultList); }); } /** * Query for a document ID with a government ID. * @param txn The {@linkcode TransactionExecutor} for lambda execute. * @param governmentId The government ID to query with. * @returns Promise which fulfills with the document ID as a string. */ export async function getDocumentIdByGovId(txn: TransactionExecutor, governmentId: string): Promise<string> { const documentId: string = await getDocumentId(txn, PERSON_TABLE_NAME, "GovId", governmentId); return documentId; } /** * Check whether a driver has already been registered for the given VIN. * @param txn The {@linkcode TransactionExecutor} for lambda execute. * @param vin VIN of the vehicle to query. * @param secondaryOwnerId The secondary owner's person ID. * @returns Promise which fulfills with a boolean. */ export async function isSecondaryOwnerForVehicle( txn: TransactionExecutor, vin: string, secondaryOwnerId: string ): Promise<boolean> { log(`Finding secondary owners for vehicle with VIN: ${vin}`); const query: string = "SELECT Owners.SecondaryOwners FROM VehicleRegistration AS v WHERE v.VIN = ?"; let doesExist: boolean = false; await txn.execute(query, vin).then((result: Result) => { const resultList: dom.Value[] = result.getResultList(); resultList.forEach((value: dom.Value) => { const secondaryOwnersList: dom.Value[] = value.get("SecondaryOwners").elements(); secondaryOwnersList.forEach((secondaryOwner) => { const personId: dom.Value = secondaryOwner.get("PersonId"); if (personId !== null && personId.stringValue() === secondaryOwnerId) { doesExist = true; } }); }); }); return doesExist; } /** * Finds and adds secondary owners for a vehicle. * @returns Promise which fulfills with void. */ const main = async function(): Promise<void> { try { const qldbDriver: QldbDriver = getQldbDriver(); const vin: string = VEHICLE_REGISTRATION[1].VIN; const govId: string = PERSON[0].GovId; await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { const documentId: string = await getDocumentIdByGovId(txn, govId); if (await isSecondaryOwnerForVehicle(txn, vin, documentId)) { log(`Person with ID ${documentId} has already been added as a secondary owner of this vehicle.`); } else { await addSecondaryOwner(txn, vin, documentId); } }); log("Secondary owners successfully updated."); } catch (e) { error(`Unable to add secondary owner: ${e}`); } } if (require.main === module) { main(); }
  4. トランスパイルされたプログラムを実行するには、次のコマンドを入力します。

    node dist/AddSecondaryOwner.js

これらの変更を vehicle-registration 台帳で確認するには、「ステップ 6: ドキュメントのリビジョン履歴を表示する」を参照してください。