使用Composer查询语言和REST API查询教程
使用Composer查询语言和REST API查询教程
在本教程中,我们将基于开发人员教程,将其扩展为演示查询。本机查询语言可以过滤使用条件返回的结果,并且可以在事务中调用以执行操作,例如更新或删除结果集上的资产。
查询.qry
在业务网络定义的父目录中的查询文件()中定义。查询包含WHERE子句,该子句定义选择资产或参与者的条件。
本教程使用Developer-Tutorial中tutorial-network
开发和部署的业务网络。
先决条件
在开始本教程之前:
第一步:更新业务网络
必须更新在开发人员教程中创建的业务网络。更新的业务网络包含两个事件和一个附加事务。
更新模型文件
必须更新模型文件以包含事件和新事务。
-
打开的model(
.cto
)文件tutorial-network
。 -
将以下事件和事务添加到模型:
复制event TradeNotification { --> Commodity commodity } transaction RemoveHighQuantityCommodities { } event RemoveNotification { --> Commodity commodity }
-
将更改保存到模型中。
更新事务逻辑以使用查询和事件
现在域模型已经更新,我们可以编写在提交事务进行处理时执行的其他业务逻辑。在本教程中,我们将事件和查询添加到下面的业务逻辑中。
-
打开事务处理器功能文件
lib/logic.js
。 -
使用以下JavaScript替换事务逻辑:
复制/** * Track the trade of a commodity from one trader to another * @param {org.example.mynetwork.Trade} trade - the trade to be processed * @transaction */ async function tradeCommodity(trade) { // set the new owner of the commodity trade.commodity.owner = trade.newOwner; let assetRegistry = await getAssetRegistry('org.example.mynetwork.Commodity'); // emit a notification that a trade has occurred let tradeNotification = getFactory().newEvent('org.example.mynetwork', 'TradeNotification'); tradeNotification.commodity = trade.commodity; emit(tradeNotification); // persist the state of the commodity await assetRegistry.update(trade.commodity); } /** * Remove all high volume commodities * @param {org.example.mynetwork.RemoveHighQuantityCommodities} remove - the remove to be processed * @transaction */ async function removeHighQuantityCommodities(remove) { let assetRegistry = await getAssetRegistry('org.example.mynetwork.Commodity'); let results = await query('selectCommoditiesWithHighQuantity'); for (let n = 0; n < results.length; n++) { let trade = results[n]; // emit a notification that a trade was removed let removeNotification = getFactory().newEvent('org.example.mynetwork','RemoveNotification'); removeNotification.commodity = trade; emit(removeNotification); await assetRegistry.remove(trade); } }
-
保存您的更改
logic.js
。
第一个函数tradeCommodity
将在传入的Trade事务上更改商品(具有新所有者Participant)的所有者属性,并发出此类通知事件。然后,它将修改后的商品保留回资产注册表,该资产注册表用于存储商品实例。
第二个函数调用命名查询'selectCommoditiesWithHighQuantity'(定义中queries.qry
),它将返回数量> 60的所有商品资产记录; 发出一个事件; 并从AssetRegistry中删除商品。
第二步:创建查询定义文件
事务处理器逻辑使用的查询在必须调用的文件中定义queries.qry
。每个查询条目定义执行查询的资源和条件。
-
在
tutorial-network
目录中,创建一个名为的新文件queries.qry
。 -
将以下代码复制并粘贴到
复制queries.qry
:/** Sample queries for Commodity Trading business network */ query selectCommodities { description: "Select all commodities" statement: SELECT org.example.mynetwork.Commodity } query selectCommoditiesByExchange { description: "Select all commodities based on their main exchange" statement: SELECT org.example.mynetwork.Commodity WHERE (mainExchange==_$exchange) } query selectCommoditiesByOwner { description: "Select all commodities based on their owner" statement: SELECT org.example.mynetwork.Commodity WHERE (owner == _$owner) } query selectCommoditiesWithHighQuantity { description: "Select commodities based on quantity" statement: SELECT org.example.mynetwork.Commodity WHERE (quantity > 60) }
-
保存您的更改
queries.qry
。
第三步:重新生成您的业务网络存档
更改业务网络中的文件后,必须将业务网络重新打包为业务网络存档(.bna
)并重新部署到Hyperledger Fabric实例。升级已部署的网络要求部署的新版本具有新版本号。
-
在
tutorial-network
目录中,打开package.json
文件。 -
更新版本从属性
0.0.1
到0.0.2
。 -
使用命令行导航到该
tutorial-network
目录。 -
运行以下命令:
复制composer archive create --sourceType dir --sourceName . -a [email protected]
第四步:部署更新的业务网络定义
我们需要部署修改后的网络,成为区块链的最新版本!我们正在使用新创建的归档业务网络归档文件来更新现有的已部署业务网络; 这是我们在开发人员教程中使用的相同业务网络名称。
-
切换到终端,将目录更改为包含该文件夹的文件夹
[email protected]
。 -
运行以下命令以安装更新的业务网络:
复制composer network install --card [email protected] --archiveFile [email protected]
-
运行以下命令将网络升级到新版本:
复制composer network upgrade -c [email protected] -n tutorial-network -V 0.0.2
-
在继续使用以下命令之前,请检查当前版本的业务网络:
复制composer network ping -c [email protected] | grep Business
第五步:为更新的业务网络重新生成REST API
我们现在将新更新的业务网络与添加的查询集成在一起,并为此业务网络公开REST API。
-
使用命令行导航到该
tutorial-network
目录。 -
使用以下命令启动REST服务器:
复制composer-rest-server
-
输入
[email protected]
卡名称。 -
当被问及是否在生成的API中使用名称空间时,请选择从不使用名称空间。
-
当询问是否保护生成的API时,请选择“ 否”。
-
当询问是否启用事件发布时,请选择“ 是 ”。
-
当询问是否启用TLS安全性时,请选择“ 否”。
第六步:测试REST API并创建一些数据
打开Web浏览器并导航到http://localhost:3000 /资源管理器。您应该看到LoopBack API Explorer,允许您检查和测试生成的REST API。
我们应该能够看到已添加名为“Query”的REST端点,并在扩展时显示业务网络中定义的REST查询操作列表 tutorial-network
在我们继续之前,我们需要创建一些数据,以充分展示查询。使用提供的示例JSON数据,使用REST API创建3个交易者(参与者)和一些其他商品(资产)。
-
首先,单击REST Explorer中的“Trader”,然后单击/ Trader上的“POST”方法,然后向下滚动到“参数”部分 - 依次创建以下Trader实例:
复制{ "$class": "org.example.mynetwork.Trader", "tradeId": "TRADER1", "firstName": "Jenny", "lastName": "Jones" }
-
点击“试用”以创建参与者。“响应代码”(向下滚动)应为200(成功)
-
通过复制以下JSON创建另一个交易者:
复制{ "$class": "org.example.mynetwork.Trader", "tradeId": "TRADER2", "firstName": "Jack", "lastName": "Sock" }
-
通过处理以下JSON创建第三个交易者:
复制{ "$class": "org.example.mynetwork.Trader", "tradeId": "TRADER3", "firstName": "Rainer", "lastName": "Valens" }
-
现在滚动到顶部并单击REST Explorer中的“Commodity”对象。
-
单击POST操作并向下滚动到Parameters部分:以与上面相同的方式,为所有者TRADER1和TRADER2创建两个商品资产记录(见下文):
复制
{
"$class": "org.example.mynetwork.Commodity",
"tradingSymbol": "EMA",
"description": "Corn",
"mainExchange": "EURONEXT",
"quantity": 10,
"owner": "resource:org.example.mynetwork.Trader#TRADER1"
}
复制
{
"$class": "org.example.mynetwork.Commodity",
"tradingSymbol": "CC",
"description": "Cocoa",
"mainExchange": "ICE",
"quantity": 80,
"owner": "resource:org.example.mynetwork.Trader#TRADER2"
}
第七步:使用商品交易REST API资源管理器执行查询
现在我们有了一些资产和参与者,我们可以使用生成的Query REST操作测试一些查询。
执行简单的REST查询
既然我们有资产和参与者,我们可以尝试一些查询。
我们可以首先尝试的最简单的REST查询是我们的命名查询selectCommodities
。
展开“查询”REST端点,您将看到我们在模型中定义的命名查询。
这些查询现在作为REST查询公开,并为其生成/ GET操作。请注意,查询的描述(我们在模型定义中定义)显示在右侧。
-
展开
selectCommodities
查询。 -
点击“试用”按钮。
它将返回所有现有的商品 - 应该返回2个资产。
执行过滤的REST查询
让我们通过他们的交易所选择所有商品 - 例如'EURONEXT'主要交易所。
-
展开查询Endpoint'selectCommoditiesByExchange'并滚动到'Parameters'部分。
-
在“Exchange”参数中输入“EURONEXT”。
-
点击“试一试”。
结果显示,只有那些交换“EURONEXT”的商品才会显示在回复正文中
使用命名Query的结果执行事务更新
最后,您会记得我们已经定义了一个简单的查询,该查询在我们的查询文件中过滤数量大于60的商品。当在事务函数中使用时,查询非常强大,因为使用查询允许事务逻辑设置资产或参与者集以执行更新,或者例如创建删除操作。
我们selectCommoditiesWithHighQuantity
在removeHighQuantityCommodities
事务中使用查询。如果在REST资源管理器中执行此/ GET操作,您将看到它仅选择数量大于60的资产。
现在让我们使用查询来删除大量商品。
首先检查自己有多少商品存在(使用'商品'/ GET操作),你应该看到至少两个商品,其中一个(可可)的数量> 60。
让我们看看实际的查询,点击REST端点/selectCommoditiesWithHighQuantity
并点击/ GET然后向下滚动到'试一试' - 应该有一个符合条件的商品。
好。现在让我们执行一个REST事务,它使用我们的“高数量”查询定义来决定要删除哪些商品。
单击RemoveHighQuantityCommodities REST端点以显示/ POST操作。
点击POST,向下滚动到参数部分,并点击“试一试外” -请注意:你不是必须在“数据”部分输入任何数据。
向下滚动,您应该看到一个transactionId,它表示事务处理器函数内部的“删除”调用(本身就是一个区块链事务),它将更新世界状态 - 响应代码应为200
最后,让我们验证我们的商品状态。返回'Commodity'REST操作并再次执行/ GET操作....'试一试'。
结果应该表明商品资产'可可'现在已经消失,即只有那些数量<= 60的商品资产仍然存在,即我们的例子中的资产'玉米'。命名查询提供了事务更新(以删除大量商品)并在业务逻辑中执行。
恭喜!
干得好,您现在已经完成了本教程,我们希望您现在可以更好地了解Composer中查询的强大功能。您可以开始创建/构建自己的查询(或修改现有查询并将相关数据添加到此业务网络 - 请注意:您需要重新部署任何查询更改)以试用!