Contents


Create powerful blockchain queries with Hyperledger Composer

The native Query language and REST APIs make it easy to query your business network's distributed ledger

Comments

For application developers, querying resources, such as assets and transaction data in blocks on a blockchain, can be a potentially circuitous task. You may wonder: How do I compose business queries that can be understood by the blockchain? How do I get the results? And how do I consume the results? You should not be burdened by the disparate nature of data in varying formats, transforming and then extracting results sets in a presentable way. Instead, your task of submitting and then handling query results should be simple and clean.

Consider these logical queries, for example:

  • "Show me the list of commodities created by Trader A."
  • "Show me the list of commodities of type EURONEXT created by Trader B in the last week."
  • "Show me the history of changes to the ledger for a particular Commodity instance, by a particular Trader, and for a specified time window."

How do you translate these queries into "blockchain speak"?

You can compose powerful queries like these with ease by using Hyperledger Composer's rich Query feature. The Query feature bridges the gap, so you no longer need to build the syntax, parse, convert, and validate the query, its types, and the results you get back from a Hyperledger Fabric blockchain. You also don't need to worry about ensuring a consistent format. Hyperledger Composer's Query language removes those hassles and makes it easy to define queries, in simple notation, and enable your application to take actions based on business-defined criteria. You can then easily consume the queries directly in your application or via the generated query REST APIs.

Hyperledger Composer is based on Hyperledger Fabric v1.0, but prior to Hyperledger Fabric v1.0, queries required IDs generated by Hyperledger Fabric. Now with Hyperledger Composer's rich query capability and Hyperledger Fabric v1.0, you can query resources using any attribute or variable parameters. By using queries with parameters, you don't have to construct complex ad hoc queries, and you can construct template queries, setting the parameters on each use.

About this tutorial

This tutorial demonstrates the power of the Hyperledger Composer Query language to return results using a blockchain resource's attributes. As an example, we'll take an existing trade-network sample deployed using Hyperledger Composer and show how to use rich queries with a REST server and how to perform operations on result sets, such as updating or removing assets using a transaction processor. The trade-network sample shows the transfer of ownership of commodities between two Traders.

All you need to work through this tutorial is the software listed below, and a working knowledge of JSON and basic query definitions. Once you've gone through the tutorial, feel free to use Hyperledger Composer to build your network and try out your own queries!

Software requirements

  • Hyperledger Composer development tools. (You'll install them in the next section.)
    • Hyperledger Composer command line (composer-cli)
    • Hyperledger Composer REST server (composer-rest-server)
  • A running Hyperledger Fabric runtime, v1 GA edition. (Instructions for downloading and starting the Hyperledger Fabric environment are in the next section.)
  • See the other prerequisites for installing the development tools.
1

Set up the Hyperledger Composer runtime with CouchDB

  1. Install the Hyperledger Composer development tools (as a non-root user):
    1. To install composer-cli, run the following command:
      npm install -g composer-cli

      The composer-cli contains all the command-line operations for developing business networks.

    2. To install composer-rest-server, run the following command:
      npm install -g composer-rest-server

      The Hyperledger Composer REST server uses the Hyperledger Composer Loopback Connector to connect to a business network, extract the models and schema for the network, and then generate the REST Explorer web page containing the REST APIs that have been generated for the model.

      For this tutorial, you will only need to use these two tools.

  2. Start the Hyperledger Fabric runtime by following the instructions in Installing and developing with Hyperledger Composer.

    After it's started, you should see the four Docker services below via this command:

    docker ps -a

    In order to use rich queries, both a CouchDB image and CouchDB configuration need to be set up and enabled. Both have been done in the Hyperledger Composer v0.11+ with the Hyperledger Fabric V1 runtime. You can enable CouchDB for each peer or a specific peer, and set the peer to depend on it. A CouchDB instance is configured for the peer with CouchDB enabled.

    A docker-compose.yml file with the appropriate configuration looks like this example:

2

Add a query to a business network

The Hyperledger Composer Query language follows the CouchDB Mango query language standards. Queries are JSON objects defined in a query file (.qry) in the business network definition. Queries can be used to return the following resources:

  • Assets
  • Participants
  • Historian data

For this tutorial, we'll use simple queries defined in the Hyperledger Composer trade-network sample, which you can download from GitHub.

Queries use a simple syntax, defined by the initial query keyword, followed by the query name, in this case selectCommoditiesByOwner. The description field should contain a meaningful, human-readable description of the query's function. The statement field contains the SELECT attribute, which defines the registry or set of resources to query, and the WHERE attribute, which defines the conditions that must be fulfilled to return resources. The WHERE attribute can contain semantic AND/OR modifiers. For more details, see the Hyperledger Composer Query Language documentation.

To add a query, open an existing business network, and create a queries.qry file. In this file, you can describe multiple queries. The example query below will return all commodities where the owner attribute matches the _$owner variable parameter supplied when the query is sent.


The Historian feature in Hyperledger Composer maintains a history of ledger updates that have occurred in a business network. When a transaction is submitted, the HistorianRecord is updated, and over time, a registry of transactions is built up, including the transaction inputs for a particular transaction as well as the participants and identities involved in submitting those transactions. To demonstrate the Historian feature in Hyperledger Composer, two additional transactions are added to the queries.qry file:

 

Listing 1. Example query with additional transactions
query showCommodityAllHistorians{ 
  description: "Select commodity all historians" 
  statement: 
    SELECT org.hyperledger.composer.system.HistorianRecord FROM 
HistorianRegistry
          WHERE (transactionType == 'AddAsset' OR transactionType == 
'UpdateAsset' OR transactionType == 'RemoveAsset') 
} 

query findCommmodityHistoriansWithTime{ 
  description: "Find commodity historians after a specified time" 
  statement: 
    SELECT org.hyperledger.composer.system.HistorianRecord FROM 
HistorianRegistry WHERE (transactionTimestamp > _$justnow) 
}

You can cut and paste these two queries into the queries.qry file and save the file.

3

Deploy the business network to Hyperledger Fabric

Now you should have a business network that includes the queries.qry file. If you have a local instance of Hyperledger Fabric, you can deploy the business network with the following command:

composer network deploy -p hlfv1 -a ./trade-network.bna -i PeerAdmin -s adminpw

You can pass a full path to the trade-network.bna; the hlfv1 is the connection profile name to the Hyperledger Fabric runtime. For more details, see the Hyperledger Composer Command Line documentation.

If you have already deployed the trade-network.bna, you should instead update the business network with this command:

                composer network update -p hlfv1 -a ./trade-network.bna -i PeerAdmin -s adminpw

You should see a successful deployment message:

Once your business network has been deployed, the following command should show a chaincode container:

docker ps –a
4

Expose rich queries via a REST API

Now that your business network containing queries is deployed, launch the Composer REST server to expose the queries through a REST API. The Hyperledger Composer REST server generates a bespoke set of REST APIs based on your business network.

  1. Start the REST server from the command line with the following command:
    composer-rest-server
  2. Provide information as shown below:
  3. Open the REST server from a web browser by typing:
    http://localhost:3000/explorer

You should see the query APIs below:

Currently, your business network is unlikely to have any data to query at this point. In the next step, you'll create some participants, assets, and a Historian registry to test the queries.

5

Create participants, assets, and a Historian registry in the World State database

In this section, we'll create two participants and two assets, and submit a trade transaction.

Create two participants

You can create participants from the REST server interface. Click Trader and then POST to create a Trader participant. The Trader participant requires three fields, as shown below. Do this twice to create two participants.

Listing 2. An example of a trader participant
{
    "$class": "org.acme.trading.Trader",
    "tradeId": "fenglian@email.com",
    "firstName": "Fenglian",
    "lastName": "Xu"
}

Create two commodity assets

Next, we'll create two Commodity assets in the same way we created participants. Do this twice to create two commodities.

Listing 3. An example of a commodity asset
{
  "$class": "org.acme.trading.Commodity",
  "tradingSymbol": "XYZ",
  "description": "Soya",
  "mainExchange": "Chicago",
  "quantity": 50,
  "owner": "dan@email.com"
}

Click GET under the Commodity to show all commodities created.

Listing 4. Two commodities created in the asset registry
[
  {
    "$class": "org.acme.trading.Commodity",
    "tradingSymbol": "EMA",
    "description": "Corn",
    "mainExchange": "Euronext",
    "quantity": 100,
    "owner": "resource:org.acme.trading.Trader#dan@email.com"
  },
  {
    "$class": "org.acme.trading.Commodity",
    "tradingSymbol": "XYZ",
    "description": "Soya",
    "mainExchange": "Chicago",
    "quantity": 50,
    "owner": "resource:org.acme.trading.Trader#dan@email.com"
  }
]

Note that the owner attribute has a relationship to a Participant instance. That is, it was modeled as such in the trade-network model. The id dan@email.com in the Participant registry (to which the fully qualified relationship refers) has a URI prefix of resource:org.acme.trading.Trader# to the participant in question.

Create a trade transaction

A trade transaction (in our example) is a transaction defined to change the ownership of a Commodity. All transactions are recorded in the Historian registry for this commodities-trading business network. It maintains a history of transactions, their types, and the changes/deltas (or additions in the case of a create such as create asset) added by a particular transaction.

Navigate to the Trade section and open POST.

In the data field put the following data:

Listing 5. An example of a trade transaction
{
  "$class": "org.acme.trading.Trade",
  "commodity": "EMA",
  "newOwner": "fenglian@email.com",
  "transactionId": "",
  "timestamp": "2017-08-07T15:04:33.790Z"
}

Then click the Try it out! button to submit the trade transaction. This transaction changes the EMA commodity's owner from dan to fenglian. You can verify this by clicking Try it out! under the Commodity GET query.

Listing 6. Updated EMA commodity owner
[
  {
    "$class": "org.acme.trading.Commodity",
    "tradingSymbol": "EMA",
    "description": "Corn",
    "mainExchange": "Euronext",
    "quantity": 100,
    "owner": "resource:org.acme.trading.Trader#fenglian@email.com"
  },
  {
    "$class": "org.acme.trading.Commodity",
    "tradingSymbol": "XYZ",
    "description": "Soya",
    "mainExchange": "Chicago",
    "quantity": 50,
    "owner": "resource:org.acme.trading.Trader#dan@email.com"
  }
]
6

Query resources via the REST server

In this section, we'll use the rich Query functions and variable parameters to query business network data via the REST server.

Rich query data type support in Hyperledger Composer and REST server

The data types for parameters in queries exposed through the REST APIs differ from the Composer data types due to the Hyperledger Composer Loopback Connector, as shown in Table 1.

Primitive data type mapping between Composer and the REST server
Component
Composer runtimeStringDouble/Integer/LongDateTimeBoolean
REST serverstringnumberdateboolean

In addition to the above Composer runtime primitive data types, the Composer runtime also supports these data types:

  • An associated relationship: This is always identified by a key property with a String type.
  • A class containment relationship: The property data type is a class that can have another class containment relationship, etc. This is a nested relationship, and it is one of the primitive types.
  • Enumerate: This is for a set of predefined data.

Query assets with parameters

Expand the query in the REST server UI. There is a list of queries defined in the queries.qry file earlier. You can use any of these to query the business network data now in the CouchDB database.

The selectComoditiesByExchange query allows you to return commodities by the exchange symbol attribute.

Click Try it out! to send the query. Results will be displayed under the Try it out! button:

The response page shows the Curl and the web browser URL for the query format with a parameter.

The selectCommoditiesByOwner query demonstrates a query using the owner attribute. You can open the GET panel for the selectCommoditiesByOwner query and define the owner you wish to query:

The query result is shown below for the specified owner.

Query transaction Historian

Historian is a Hyperledger Composer feature used to track transactions and asset updates. When a transaction is submitted, the HistorianRecord shows the changes to assets in a business network, and the participants and identities involved in submitting those transactions.

The Historian is an asset defined in the Hyperledger Composer system name space, as shown in Listing 7.

If you want to programmatically use the Historian, see the Hyperledger Composer Historian Record documentation.

Listing 7. Historian model
asset HistorianRecord identified by transactionId {
  o String      transactionId
  o String      transactionType
  --> Transaction transactionInvoked
  --> Participant participantInvoking  optional
  --> Identity    identityUsed         optional
  o Event[]       eventsEmitted        optional
  o DateTime      transactionTimestamp
}

Navigate to the findCommodityHistoriansWithTime query, specify a date time value in UTC format, and click Try it out!

This query finds all Historian records of transactions after the specified date time in the Historian registry as shown in Listing 8. The transaction type includes both system transactions and user-defined transactions. For example, the Trade is a user-defined transaction, and the AddAsset is a system transaction.

Listing 8. Historian records of transactions
[
  {
    "$class": "org.hyperledger.composer.system.HistorianRecord",
    "transactionId": "0392a2e7-e056-4442-82c7-7d020cd0ee7a",
    "transactionType": "AddParticipant",
    "transactionInvoked": "resource:org.hyperledger.composer.system.Transaction#0392a2e7-e056-4442-82c7-7d020cd0ee7a",
    "eventsEmitted": [],
    "transactionTimestamp": "2017-08-07T15:08:19.047Z"
  },
  {
    "$class": "org.hyperledger.composer.system.HistorianRecord",
    "transactionId": "04f4410c-3470-4319-a6c5-3f5681d86488",
    "transactionType": "AddAsset",
    "transactionInvoked": "resource:org.hyperledger.composer.system.Transaction#04f4410c-3470-4319-a6c5-3f5681d86488",
    "eventsEmitted": [],
    "transactionTimestamp": "2017-08-07T15:13:56.223Z"
  },
  {
    "$class": "org.hyperledger.composer.system.HistorianRecord",
    "transactionId": "2529902c-1393-4537-98ca-f3e4d46a3164",
    "transactionType": "Trade",
    "transactionInvoked": "resource:org.hyperledger.composer.system.Transaction#2529902c-1393-4537-98ca-f3e4d46a3164",
    "eventsEmitted": [
      {
        "$class": "org.acme.trading.TradeNotification",
        "commodity": "resource:org.acme.trading.Commodity#EMA",
        "eventId": "2529902c-1393-4537-98ca-f3e4d46a3164#0",
        "timestamp": "2017-08-07T15:04:33.790Z"
      }
    ],
    "transactionTimestamp": "2017-08-07T15:04:33.790Z"
  },
  {
    "$class": "org.hyperledger.composer.system.HistorianRecord",
    "transactionId": "3f31add4-5e4d-40cd-84a5-e5553a14cb50",
    "transactionType": "AddAsset",
    "transactionInvoked": "resource:org.hyperledger.composer.system.Transaction#3f31add4-5e4d-40cd-84a5-e5553a14cb50",
    "eventsEmitted": [],
    "transactionTimestamp": "2017-08-07T15:13:03.584Z"
  },
  {
    "$class": "org.hyperledger.composer.system.HistorianRecord",
    "transactionId": "a50145ba-df31-4def-932e-cfc9707131ec",
    "transactionType": "AddParticipant",
    "transactionInvoked": "resource:org.hyperledger.composer.system.Transaction#a50145ba-df31-4def-932e-cfc9707131ec",
    "eventsEmitted": [],
    "transactionTimestamp": "2017-08-07T15:07:15.985Z"
  }
]

Conclusion

The rich Query language built into Hyperledger Composer makes it easy to perform complex and powerful queries on assets and transactions. Without this native Query language, you'd have to construct ad hoc queries in your code and then work to make sense of the results returned.

This tutorial has shown you how to define queries in Hyperledger Composer, deploy or update a business network to Hyperledger Fabric with CouchDB enabled, set up a REST server, and use the REST server to query your business network. The Hyperledger Composer Query language provides great flexibility for querying any attributes easily.

Next steps

Acknowledgments

Thanks to the Hyperledger Composer development team, and especially to Daniel Selman and Simon Stone for their technical support. Thanks also to Edward Prosser and Rachel Jackson for their technical reviews and support.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Blockchain, Cloud computing
ArticleID=1050204
ArticleTitle=Create powerful blockchain queries with Hyperledger Composer
publish-date=09262017