github.com/kaituanwang/hyperledger@v2.0.1+incompatible/docs/source/couchdb_tutorial.rst (about)

     1  
     2  Using CouchDB
     3  =============
     4  
     5  This tutorial will describe the steps required to use the CouchDB as the state
     6  database with Hyperledger Fabric. By now, you should be familiar with Fabric
     7  concepts and have explored some of the samples and tutorials.
     8  
     9  .. note:: These instructions use the new Fabric chaincode lifecycle introduced
    10            in the Fabric v2.0 release. If you would like to use the previous
    11            lifecycle model to use indexes with chaincode, visit the v1.4
    12            version of the `Using CouchDB <https://hyperledger-fabric.readthedocs.io/en/release-1.4/couchdb_tutorial.html>`__.
    13  
    14  The tutorial will take you through the following steps:
    15  
    16  #. :ref:`cdb-enable-couch`
    17  #. :ref:`cdb-create-index`
    18  #. :ref:`cdb-add-index`
    19  #. :ref:`cdb-install-deploy`
    20  #. :ref:`cdb-query`
    21  #. :ref:`cdb-best`
    22  #. :ref:`cdb-pagination`
    23  #. :ref:`cdb-update-index`
    24  #. :ref:`cdb-delete-index`
    25  
    26  For a deeper dive into CouchDB refer to :doc:`couchdb_as_state_database`
    27  and for more information on the Fabric ledger refer to the `Ledger <ledger/ledger.html>`_
    28  topic. Follow the tutorial below for details on how to leverage CouchDB in your
    29  blockchain network.
    30  
    31  Throughout this tutorial, we will use the `Marbles sample <https://github.com/hyperledger/fabric-samples/blob/master/chaincode/marbles02/go/marbles_chaincode.go>`__
    32  as our use case to demonstrate how to use CouchDB with Fabric and will deploy
    33  Marbles to the Fabric test network. You should have completed the task
    34  :doc:`install`.
    35  
    36  Why CouchDB?
    37  ~~~~~~~~~~~~
    38  
    39  Fabric supports two types of peer databases. LevelDB is the default state
    40  database embedded in the peer node. LevelDB stores chaincode data as simple
    41  key-value pairs and only supports key, key range, and composite key queries.
    42  CouchDB is an optional, alternate state database that allows you to model data
    43  on the ledger as JSON and issue rich queries against data values rather than
    44  the keys. CouchDB also allows you to deploy indexes with your chaincode to make
    45  queries more efficient and enable you to query large datasets.
    46  
    47  In order to leverage the benefits of CouchDB, namely content-based JSON
    48  queries, your data must be modeled in JSON format. You must decide whether to use
    49  LevelDB or CouchDB before setting up your network. Switching a peer from using
    50  LevelDB to CouchDB is not supported due to data compatibility issues. All peers
    51  on the network must use the same database type. If you have a mix of JSON and
    52  binary data values, you can still use CouchDB, however the binary values can
    53  only be queried based on key, key range, and composite key queries.
    54  
    55  .. _cdb-enable-couch:
    56  
    57  Enable CouchDB in Hyperledger Fabric
    58  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    59  
    60  CouchDB runs as a separate database process alongside the peer. There
    61  are additional considerations in terms of setup, management, and operations.
    62  A Docker image of `CouchDB <https://hub.docker.com/_/couchdb/>`__
    63  is available and we recommend that it be run on the same server as the
    64  peer. You will need to setup one CouchDB container per peer
    65  and update each peer container by changing the configuration found in
    66  ``core.yaml`` to point to the CouchDB container. The ``core.yaml``
    67  file must be located in the directory specified by the environment variable
    68  FABRIC_CFG_PATH:
    69  
    70  * For Docker deployments, ``core.yaml`` is pre-configured and located in the peer
    71    container ``FABRIC_CFG_PATH`` folder. However, when using Docker environments,
    72    you typically pass environment variables by editing the
    73    ``docker-compose-couch.yaml``  to override the core.yaml
    74  
    75  * For native binary deployments, ``core.yaml`` is included with the release artifact
    76    distribution.
    77  
    78  Edit the ``stateDatabase`` section of ``core.yaml``. Specify ``CouchDB`` as the
    79  ``stateDatabase`` and fill in the associated ``couchDBConfig`` properties. For
    80  more information, see `CouchDB configuration <couchdb_as_state_database.html#couchdb-configuration>`__.
    81  
    82  .. _cdb-create-index:
    83  
    84  Create an index
    85  ~~~~~~~~~~~~~~~
    86  
    87  Why are indexes important?
    88  
    89  Indexes allow a database to be queried without having to examine every row
    90  with every query, making them run faster and more efficiently. Normally,
    91  indexes are built for frequently occurring query criteria allowing the data to
    92  be queried more efficiently. To leverage the major benefit of CouchDB -- the
    93  ability to perform rich queries against JSON data -- indexes are not required,
    94  but they are strongly recommended for performance. Also, if sorting is required
    95  in a query, CouchDB requires an index of the sorted fields.
    96  
    97  .. note::
    98  
    99     Rich queries that do not have an index will work but may throw a warning
   100     in the CouchDB log that the index was not found. However, if a rich query
   101     includes a sort specification, then an index on that field is required;
   102     otherwise, the query will fail and an error will be thrown.
   103  
   104  To demonstrate building an index, we will use the data from the `Marbles
   105  sample <https://github.com/hyperledger/fabric-samples/blob/master/chaincode/marbles02/go/marbles_chaincode.go>`__.
   106  In this example, the Marbles data structure is defined as:
   107  
   108  .. code:: javascript
   109  
   110    type marble struct {
   111  	   ObjectType string `json:"docType"` //docType is used to distinguish the various types of objects in state database
   112  	   Name       string `json:"name"`    //the field tags are needed to keep case from bouncing around
   113  	   Color      string `json:"color"`
   114             Size       int    `json:"size"`
   115             Owner      string `json:"owner"`
   116    }
   117  
   118  
   119  In this structure, the attributes (``docType``, ``name``, ``color``, ``size``,
   120  ``owner``) define the ledger data associated with the asset. The attribute
   121  ``docType`` is a pattern used in the chaincode to differentiate different data
   122  types that may need to be queried separately. When using CouchDB, it
   123  recommended to include this ``docType`` attribute to distinguish each type of
   124  document in the chaincode namespace. (Each chaincode is represented as its own
   125  CouchDB database, that is, each chaincode has its own namespace for keys.)
   126  
   127  With respect to the Marbles data structure, ``docType`` is used to identify
   128  that this document/asset is a marble asset. Potentially there could be other
   129  documents/assets in the chaincode database. The documents in the database are
   130  searchable against all of these attribute values.
   131  
   132  When defining an index for use in chaincode queries, each one must be defined
   133  in its own text file with the extension `*.json` and the index definition must
   134  be formatted in the CouchDB index JSON format.
   135  
   136  To define an index, three pieces of information are required:
   137  
   138    * `fields`: these are the frequently queried fields
   139    * `name`: name of the index
   140    * `type`: always json in this context
   141  
   142  For example, a simple index named ``foo-index`` for a field named ``foo``.
   143  
   144  .. code:: json
   145  
   146      {
   147          "index": {
   148              "fields": ["foo"]
   149          },
   150          "name" : "foo-index",
   151          "type" : "json"
   152      }
   153  
   154  Optionally the design document  attribute ``ddoc`` can be specified on the index
   155  definition. A `design document <http://guide.couchdb.org/draft/design.html>`__ is
   156  CouchDB construct designed to contain indexes. Indexes can be grouped into
   157  design documents for efficiency but CouchDB recommends one index per design
   158  document.
   159  
   160  .. tip:: When defining an index it is a good practice to include the ``ddoc``
   161           attribute and value along with the index name. It is important to
   162           include this attribute to ensure that you can update the index later
   163           if needed. Also it gives you the ability to explicitly specify which
   164           index to use on a query.
   165  
   166  
   167  Here is another example of an index definition from the Marbles sample with
   168  the index name ``indexOwner`` using multiple fields ``docType`` and ``owner``
   169  and includes the ``ddoc`` attribute:
   170  
   171  .. _indexExample:
   172  
   173  .. code:: json
   174  
   175    {
   176      "index":{
   177          "fields":["docType","owner"] // Names of the fields to be queried
   178      },
   179      "ddoc":"indexOwnerDoc", // (optional) Name of the design document in which the index will be created.
   180      "name":"indexOwner",
   181      "type":"json"
   182    }
   183  
   184  In the example above, if the design document ``indexOwnerDoc`` does not already
   185  exist, it is automatically created when the index is deployed. An index can be
   186  constructed with one or more attributes specified in the list of fields and
   187  any combination of attributes can be specified. An attribute can exist in
   188  multiple indexes for the same docType. In the following example, ``index1``
   189  only includes the attribute ``owner``, ``index2`` includes the attributes
   190  ``owner and color`` and ``index3`` includes the attributes ``owner, color and
   191  size``. Also, notice each index definition has its own ``ddoc`` value, following
   192  the CouchDB recommended practice.
   193  
   194  .. code:: json
   195  
   196    {
   197      "index":{
   198          "fields":["owner"] // Names of the fields to be queried
   199      },
   200      "ddoc":"index1Doc", // (optional) Name of the design document in which the index will be created.
   201      "name":"index1",
   202      "type":"json"
   203    }
   204  
   205    {
   206      "index":{
   207          "fields":["owner", "color"] // Names of the fields to be queried
   208      },
   209      "ddoc":"index2Doc", // (optional) Name of the design document in which the index will be created.
   210      "name":"index2",
   211      "type":"json"
   212    }
   213  
   214    {
   215      "index":{
   216          "fields":["owner", "color", "size"] // Names of the fields to be queried
   217      },
   218      "ddoc":"index3Doc", // (optional) Name of the design document in which the index will be created.
   219      "name":"index3",
   220      "type":"json"
   221    }
   222  
   223  
   224  In general, you should model index fields to match the fields that will be used
   225  in query filters and sorts. For more details on building an index in JSON
   226  format refer to the `CouchDB documentation <http://docs.couchdb.org/en/latest/api/database/find.html#db-index>`__.
   227  
   228  A final word on indexing, Fabric takes care of indexing the documents in the
   229  database using a pattern called ``index warming``. CouchDB does not typically
   230  index new or updated documents until the next query. Fabric ensures that
   231  indexes stay 'warm' by requesting an index update after every block of data is
   232  committed.  This ensures queries are fast because they do not have to index
   233  documents before running the query. This process keeps the index current
   234  and refreshed every time new records are added to the state database.
   235  
   236  .. _cdb-add-index:
   237  
   238  
   239  Add the index to your chaincode folder
   240  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   241  
   242  Once you finalize an index, you need to package it with your chaincode for
   243  deployment by placing it in the appropriate metadata folder. You can install the
   244  chaincode using the :doc:`commands/peerlifecycle` command. The JSON index files
   245  must be located under the path ``META-INF/statedb/couchdb/indexes`` which is
   246  located inside the directory where the chaincode resides.
   247  
   248  The `Marbles sample <https://github.com/hyperledger/fabric-samples/tree/master/chaincode/marbles02/go>`__  below illustrates how the index
   249  is packaged with the chaincode.
   250  
   251  .. image:: images/couchdb_tutorial_pkg_example.png
   252    :scale: 100%
   253    :align: center
   254    :alt: Marbles Chaincode Index Package
   255  
   256  This sample includes one index named indexOwnerDoc:
   257  
   258  .. code:: json
   259  
   260    {"index":{"fields":["docType","owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"}
   261  
   262  
   263  Start the network
   264  -----------------
   265  
   266  :guilabel:`Try it yourself`
   267  
   268  
   269  We will bring up the Fabric test network and use it to deploy the marbles
   270  chainocde. Use the following command to navigate to the `test-network` directory
   271  in the Fabric samples:
   272  
   273  .. code:: bash
   274  
   275      cd fabric-samples/test-network
   276  
   277  For this tutorial, we want to operate from a known initial state. The following
   278  command will kill any active or stale Docker containers and remove previously
   279  generated artifacts:
   280  
   281  .. code:: bash
   282  
   283      ./network.sh down
   284  
   285  If you have not run through the tutorial before, you will need to vendor the
   286  chaincode dependencies before we can deploy it to the network. Run the
   287  following commands:
   288  
   289  .. code:: bash
   290  
   291      cd ../chaincode/marbles02/go
   292      GO111MODULE=on go mod vendor
   293      cd ../../../test-network
   294  
   295  From the `test-network` directory, deploy the test network with CouchDB with the
   296  following command:
   297  
   298  .. code:: bash
   299  
   300      ./network.sh up createChannel -s couchdb
   301  
   302  This will create two fabric peer nodes that use CouchDB as the state database.
   303  It will also create one ordering node and a single channel named
   304  ``mychannel``.
   305  
   306  .. _cdb-install-deploy:
   307  
   308  Install and define the Chaincode
   309  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   310  
   311  Client applications interact with the blockchain ledger through chaincode.
   312  Therefore we need to install a chaincode on every peer that will execute and
   313  endorse our transactions. However, before we can interact with our chaincode,
   314  the members of the channel need to agree on a chaincode definition that
   315  establishes chaincode governance. In the previous section, we demonstrated how
   316  to add the index to the chaincode folder so that the index is deployed with
   317  the chaincode.
   318  
   319  The chaincode needs to be packaged before it can be installed on our peers.
   320  We can use the `peer lifecycle chaincode package <commands/peerlifecycle.html#peer-lifecycle-chaincode-package>`__ command
   321  to package the marbles chaincode.
   322  
   323  :guilabel:`Try it yourself`
   324  
   325  1. After you start the test network, copy and paste the following environment
   326  variables in your CLI to interact with the network as the Org1 admin. Make sure
   327  that you are in the `test-network` directory.
   328  
   329  .. code:: bash
   330  
   331      export PATH=${PWD}/../bin:${PWD}:$PATH
   332      export FABRIC_CFG_PATH=${PWD}/../config/
   333      export CORE_PEER_TLS_ENABLED=true
   334      export CORE_PEER_LOCALMSPID="Org1MSP"
   335      export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   336      export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   337      export CORE_PEER_ADDRESS=localhost:7051
   338  
   339  2. Use the following command to package the marbles chaincode:
   340  
   341  .. code:: bash
   342  
   343      peer lifecycle chaincode package marbles.tar.gz --path ../chaincode/marbles02/go --lang golang --label marbles_1
   344  
   345  This command will create a chaincode package named marbles.tar.gz.
   346  
   347  3. Use the following command to install the chaincode package onto the peer
   348  ``peer0.org1.example.com``:
   349  
   350  .. code:: bash
   351  
   352      peer lifecycle chaincode install marbles.tar.gz
   353  
   354  A successful install command will return the chaincode identifier, similar to
   355  the response below:
   356  
   357  .. code:: bash
   358  
   359      2019-04-22 18:47:38.312 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJmarbles_1:0907c1f3d3574afca69946e1b6132691d58c2f5c5703df7fc3b692861e92ecd3\022\tmarbles_1" >
   360      2019-04-22 18:47:38.312 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: marbles_1:0907c1f3d3574afca69946e1b6132691d58c2f5c5703df7fc3b692861e92ecd3
   361  
   362  After installing the chaincode on ``peer0.org1.example.com``, we need to approve
   363  a chaincode definition for Org1.
   364  
   365  4. Use the following command to query your peer for the package ID of the
   366  installed chaincode.
   367  
   368  .. code:: bash
   369  
   370      peer lifecycle chaincode queryinstalled
   371  
   372  The command will return the same package identifier as the install command.
   373  You should see output similar to the following:
   374  
   375  .. code:: bash
   376  
   377      Installed chaincodes on peer:
   378      Package ID: marbles_1:60ec9430b221140a45b96b4927d1c3af736c1451f8d432e2a869bdbf417f9787, Label: marbles_1
   379  
   380  5. Declare the package ID as an environment variable. Paste the package ID of
   381  marbles_1 returned by the ``peer lifecycle chaincode queryinstalled`` command
   382  into the command below. The package ID may not be the same for all users, so
   383  you need to complete this step using the package ID returned from your console.
   384  
   385  .. code:: bash
   386  
   387      export CC_PACKAGE_ID=marbles_1:60ec9430b221140a45b96b4927d1c3af736c1451f8d432e2a869bdbf417f9787
   388  
   389  6. Use the following command to approve a definition of the marbles chaincode
   390  for Org1.
   391  
   392  .. code:: bash
   393  
   394      export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
   395      peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --version 1.0 --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls true --cafile $ORDERER_CA
   396  
   397  When the command completes successfully you should see something similar to :
   398  
   399  .. code:: bash
   400  
   401      2020-01-07 16:24:20.886 EST [chaincodeCmd] ClientWait -> INFO 001 txid [560cb830efa1272c85d2f41a473483a25f3b12715d55e22a69d55abc46581415] committed with status (VALID) at
   402  
   403  We need a majority of organizations to approve a chaincode definition before
   404  it can be committed to the channel. This implies that we need Org2 to approve
   405  the chaincode definition as well. Because we do not need Org2 to endorse the
   406  chaincode and did not install the package on any Org2 peers, we do not need to
   407  provide a packageID as part of the chaincode definition.
   408  
   409  7. Use the CLI to operate as the Org2 admin. Copy and paste the following block
   410  of commands as a group into the peer container and run them all at once.
   411  
   412  .. code:: bash
   413  
   414      export CORE_PEER_LOCALMSPID="Org2MSP"
   415      export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
   416      export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
   417      export CORE_PEER_ADDRESS=localhost:9051
   418  
   419  8. Use the following command to approve the chaincode definition for Org2:
   420  
   421  .. code:: bash
   422  
   423      peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --version 1.0 --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --init-required --sequence 1 --tls true --cafile $ORDERER_CA
   424  
   425  9. We can now use the `peer lifecycle chaincode commit <commands/peerlifecycle.html#peer-lifecycle-chaincode-commit>`__ command
   426  to commit the chaincode definition to the channel:
   427  
   428  .. code:: bash
   429  
   430      export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
   431      export ORG1_CA=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   432      export ORG2_CA=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
   433      peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --version 1.0 --sequence 1 --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --init-required --tls true --cafile $ORDERER_CA --peerAddresses localhost:7051 --tlsRootCertFiles $ORG1_CA --peerAddresses localhost:9051 --tlsRootCertFiles $ORG2_CA
   434  
   435  When the commit transaction completes successfully you should see something
   436  similar to:
   437  
   438  .. code:: bash
   439  
   440      2019-04-22 18:57:34.274 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [3da8b0bb8e128b5e1b6e4884359b5583dff823fce2624f975c69df6bce614614] committed with status (VALID) at peer0.org2.example.com:9051
   441      2019-04-22 18:57:34.709 UTC [chaincodeCmd] ClientWait -> INFO 002 txid [3da8b0bb8e128b5e1b6e4884359b5583dff823fce2624f975c69df6bce614614] committed with status (VALID) at peer0.org1.example.com:7051
   442  
   443  10. Because the marbles chaincode contains an initialization function, we need to
   444  use the `peer chaincode invoke <commands/peerchaincode.html?%20chaincode%20instantiate#peer-chaincode-invoke>`__ command
   445  to invoke ``Init()`` before we can use other functions in the chaincode:
   446  
   447  .. code:: bash
   448  
   449      peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --isInit --tls true --cafile $ORDERER_CA --peerAddresses localhost:7051 --tlsRootCertFiles $ORG1_CA -c '{"Args":["Init"]}'
   450  
   451  Verify index was deployed
   452  -------------------------
   453  
   454  Indexes will be deployed to each peer's CouchDB state database once the
   455  chaincode has been installed on the peer and deployed to the channel. You can
   456  verify that the CouchDB index was created successfully by examining the peer log
   457  in the Docker container.
   458  
   459  :guilabel:`Try it yourself`
   460  
   461  To view the logs in the peer Docker container, open a new Terminal window and
   462  run the following command to grep for message confirmation that the index was
   463  created.
   464  
   465  ::
   466  
   467     docker logs peer0.org1.example.com  2>&1 | grep "CouchDB index"
   468  
   469  
   470  You should see a result that looks like the following:
   471  
   472  ::
   473  
   474     [couchdb] CreateIndex -> INFO 0be Created CouchDB index [indexOwner] in state database [mychannel_marbles] using design document [_design/indexOwnerDoc]
   475  
   476  .. note:: If you installed Marbles on a different peer than ``peer0.org1.example.com``,
   477            you may need to replace it with the name of a different peer where
   478            Marbles was installed.
   479  
   480  .. _cdb-query:
   481  
   482  Query the CouchDB State Database
   483  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   484  
   485  Now that the index has been defined in the JSON file and deployed alongside the
   486  chaincode, chaincode functions can execute JSON queries against the CouchDB
   487  state database, and thereby peer commands can invoke the chaincode functions.
   488  
   489  Specifying an index name on a query is optional. If not specified, and an index
   490  already exists for the fields being queried, the existing index will be
   491  automatically used.
   492  
   493  .. tip:: It is a good practice to explicitly include an index name on a
   494           query using the ``use_index`` keyword. Without it, CouchDB may pick a
   495           less optimal index. Also CouchDB may not use an index at all and you
   496           may not realize it, at the low volumes during testing. Only upon
   497           higher volumes you may realize slow performance because CouchDB is not
   498           using an index and you assumed it was.
   499  
   500  
   501  Build the query in chaincode
   502  ----------------------------
   503  
   504  You can perform complex rich queries against the data on the ledger using
   505  queries defined within your chaincode. The `marbles02 sample <https://github.com/hyperledger/fabric-samples/blob/master/chaincode/marbles02/go/marbles_chaincode.go>`__
   506  includes two rich query functions:
   507  
   508    * **queryMarbles** --
   509  
   510        Example of an **ad hoc rich query**. This is a query
   511        where a (selector) string can be passed into the function. This query
   512        would be useful to client applications that need to dynamically build
   513        their own selectors at runtime. For more information on selectors refer
   514        to `CouchDB selector syntax <http://docs.couchdb.org/en/latest/api/database/find.html#find-selectors>`__.
   515  
   516  
   517    * **queryMarblesByOwner** --
   518  
   519        Example of a **parameterized query** where the
   520        query logic is baked into the chaincode. In this case the function accepts
   521        a single argument, the marble owner. It then queries the state database for
   522        JSON documents matching the docType of “marble” and the owner id using the
   523        JSON query syntax.
   524  
   525  
   526  Run the query using the peer command
   527  ------------------------------------
   528  
   529  In absence of a client application, we can use the peer command to test the
   530  queries defined in the chaincode. We will customize the `peer chaincode query <commands/peerchaincode.html?%20chaincode%20query#peer-chaincode-query>`__
   531  command to use the Marbles index ``indexOwner`` and query for all marbles owned
   532  by "tom" using the ``queryMarbles`` function.
   533  
   534  :guilabel:`Try it yourself`
   535  
   536  Before querying the database, we should add some data. Run the following
   537  command as Org1 to create a marble owned by "tom":
   538  
   539  .. code:: bash
   540  
   541      export CORE_PEER_LOCALMSPID="Org1MSP"
   542      export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   543      export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   544      export CORE_PEER_ADDRESS=localhost:7051
   545      peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
   546  
   547  After an index has been deployed when the chaincode is initialized, it will
   548  automatically be utilized by chaincode queries. CouchDB can determine which
   549  index to use based on the fields being queried. If an index exists for the
   550  query criteria it will be used. However the recommended approach is to
   551  specify the ``use_index`` keyword on the query. The peer command below is an
   552  example of how to specify the index explicitly in the selector syntax by
   553  including the ``use_index`` keyword:
   554  
   555  .. code:: bash
   556  
   557     // Rich Query with index name explicitly specified:
   558     peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"]}'
   559  
   560  Delving into the query command above, there are three arguments of interest:
   561  
   562  *  ``queryMarbles``
   563  
   564    Name of the function in the Marbles chaincode. Notice a `shim <https://godoc.org/github.com/hyperledger/fabric-chaincode-go/shim>`__
   565    ``shim.ChaincodeStubInterface`` is used to access and modify the ledger. The
   566    ``getQueryResultForQueryString()`` passes the queryString to the shim API ``getQueryResult()``.
   567  
   568  .. code:: bash
   569  
   570    func (t *SimpleChaincode) queryMarbles(stub shim.ChaincodeStubInterface, args []string) pb.Response {
   571  
   572  	  //   0
   573  	  // "queryString"
   574  	   if len(args) < 1 {
   575  		   return shim.Error("Incorrect number of arguments. Expecting 1")
   576  	   }
   577  
   578  	   queryString := args[0]
   579  
   580  	   queryResults, err := getQueryResultForQueryString(stub, queryString)
   581  	   if err != nil {
   582  		 return shim.Error(err.Error())
   583  	   }
   584  	   return shim.Success(queryResults)
   585    }
   586  
   587  *  ``{"selector":{"docType":"marble","owner":"tom"}``
   588  
   589    This is an example of an **ad hoc selector** string which finds all documents
   590    of type ``marble`` where the ``owner`` attribute has a value of ``tom``.
   591  
   592  
   593  *  ``"use_index":["_design/indexOwnerDoc", "indexOwner"]``
   594  
   595    Specifies both the design doc name  ``indexOwnerDoc`` and index name
   596    ``indexOwner``. In this example the selector query explicitly includes the
   597    index name, specified by using the ``use_index`` keyword. Recalling the
   598    index definition above :ref:`cdb-create-index`, it contains a design doc,
   599    ``"ddoc":"indexOwnerDoc"``. With CouchDB, if you plan to explicitly include
   600    the index name on the query, then the index definition must include the
   601    ``ddoc`` value, so it can be referenced with the ``use_index`` keyword.
   602  
   603  
   604  The query runs successfully and the index is leveraged with the following results:
   605  
   606  .. code:: json
   607  
   608    Query Result: [{"Key":"marble1", "Record":{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}}]
   609  
   610  .. _cdb-best:
   611  
   612  Use best practices for queries and indexes
   613  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   614  
   615  Queries that use indexes will complete faster, without having to scan the full
   616  database in couchDB. Understanding indexes will allow you to write your queries
   617  for better performance and help your application handle larger amounts
   618  of data or blocks on your network.
   619  
   620  It is also important to plan the indexes you install with your chaincode. You
   621  should install only a few indexes per chaincode that support most of your queries.
   622  Adding too many indexes, or using an excessive number of fields in an index, will
   623  degrade the performance of your network. This is because the indexes are updated
   624  after each block is committed. The more indexes need to be updated through
   625  "index warming", the longer it will take for transactions to complete.
   626  
   627  The examples in this section will help demonstrate how queries use indexes and
   628  what type of queries will have the best performance. Remember the following
   629  when writing your queries:
   630  
   631  * All fields in the index must also be in the selector or sort sections of your query
   632    for the index to be used.
   633  * More complex queries will have a lower performance and will be less likely to
   634    use an index.
   635  * You should try to avoid operators that will result in a full table scan or a
   636    full index scan such as ``$or``, ``$in`` and ``$regex``.
   637  
   638  In the previous section of this tutorial, you issued the following query against
   639  the marbles chaincode:
   640  
   641  .. code:: bash
   642  
   643    // Example one: query fully supported by the index
   644    peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}'
   645  
   646  The marbles chaincode was installed with the ``indexOwnerDoc`` index:
   647  
   648  .. code:: json
   649  
   650    {"index":{"fields":["docType","owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"}
   651  
   652  Notice that both the fields in the query, ``docType`` and ``owner``, are
   653  included in the index, making it a fully supported query. As a result this
   654  query will be able to use the data in the index, without having to search the
   655  full database. Fully supported queries such as this one will return faster than
   656  other queries from your chaincode.
   657  
   658  If you add extra fields to the query above, it will still use the index.
   659  However, the query will additionally have to scan the indexed data for the
   660  extra fields, resulting in a longer response time. As an example, the query
   661  below will still use the index, but will take a longer time to return than the
   662  previous example.
   663  
   664  .. code:: bash
   665  
   666    // Example two: query fully supported by the index with additional data
   667    peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\",\"color\":\"red\"}, \"use_index\":[\"/indexOwnerDoc\", \"indexOwner\"]}"]}'
   668  
   669  A query that does not include all fields in the index will have to scan the full
   670  database instead. For example, the query below searches for the owner, without
   671  specifying the the type of item owned. Since the ownerIndexDoc contains both
   672  the ``owner`` and ``docType`` fields, this query will not be able to use the
   673  index.
   674  
   675  .. code:: bash
   676  
   677    // Example three: query not supported by the index
   678    peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"owner\":\"tom\"}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}'
   679  
   680  In general, more complex queries will have a longer response time, and have a
   681  lower chance of being supported by an index. Operators such as ``$or``, ``$in``,
   682  and ``$regex`` will often cause the query to scan the full index or not use the
   683  index at all.
   684  
   685  As an example, the query below contains an ``$or`` term that will search for every
   686  marble and every item owned by tom.
   687  
   688  .. code:: bash
   689  
   690    // Example four: query with $or supported by the index
   691    peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{"\$or\":[{\"docType\:\"marble\"},{\"owner\":\"tom\"}]}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}'
   692  
   693  This query will still use the index because it searches for fields that are
   694  included in ``indexOwnerDoc``. However, the ``$or`` condition in the query
   695  requires a scan of all the items in the index, resulting in a longer response
   696  time.
   697  
   698  Below is an example of a complex query that is not supported by the index.
   699  
   700  .. code:: bash
   701  
   702    // Example five: Query with $or not supported by the index
   703    peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{"\$or\":[{\"docType\":\"marble\",\"owner\":\"tom\"},{"\color\":"\yellow\"}]}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}'
   704  
   705  The query searches for all marbles owned by tom or any other items that are
   706  yellow. This query will not use the index because it will need to search the
   707  entire table to meet the ``$or`` condition. Depending the amount of data on your
   708  ledger, this query will take a long time to respond or may timeout.
   709  
   710  While it is important to follow best practices with your queries, using indexes
   711  is not a solution for collecting large amounts of data. The blockchain data
   712  structure is optimized to validate and confirm transactions and is not suited
   713  for data analytics or reporting. If you want to build a dashboard as part
   714  of your application or analyze the data from your network, the best practice is
   715  to query an off chain database that replicates the data from your peers. This
   716  will allow you to understand the data on the blockchain without degrading the
   717  performance of your network or disrupting transactions.
   718  
   719  You can use block or chaincode events from your application to write transaction
   720  data to an off-chain database or analytics engine. For each block received, the block
   721  listener application would iterate through the block transactions and build a data
   722  store using the key/value writes from each valid transaction's ``rwset``. The
   723  :doc:`peer_event_services` provide replayable events to ensure the integrity of
   724  downstream data stores. For an example of how you can use an event listener to write
   725  data to an external database, visit the `Off chain data sample <https://github.com/hyperledger/fabric-samples/tree/master/off_chain_data>`__
   726  in the Fabric Samples.
   727  
   728  .. _cdb-pagination:
   729  
   730  Query the CouchDB State Database With Pagination
   731  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   732  
   733  When large result sets are returned by CouchDB queries, a set of APIs is
   734  available which can be called by chaincode to paginate the list of results.
   735  Pagination provides a mechanism to partition the result set by
   736  specifying a ``pagesize`` and a start point -- a ``bookmark`` which indicates
   737  where to begin the result set. The client application iteratively invokes the
   738  chaincode that executes the query until no more results are returned. For more information refer to
   739  this `topic on pagination with CouchDB <couchdb_as_state_database.html#couchdb-pagination>`__.
   740  
   741  
   742  We will use the `Marbles sample <https://github.com/hyperledger/fabric-samples/blob/master/chaincode/marbles02/go/marbles_chaincode.go>`__
   743  function ``queryMarblesWithPagination`` to  demonstrate how
   744  pagination can be implemented in chaincode and the client application.
   745  
   746  * **queryMarblesWithPagination** --
   747  
   748      Example of an **ad hoc rich query with pagination**. This is a query
   749      where a (selector) string can be passed into the function similar to the
   750      above example.  In this case, a ``pageSize`` is also included with the query as
   751      well as a ``bookmark``.
   752  
   753  In order to demonstrate pagination, more data is required. This example assumes
   754  that you have already added marble1 from above. Run the following commands in
   755  the peer container to create four more marbles owned by "tom", to create a
   756  total of five marbles owned by "tom":
   757  
   758  :guilabel:`Try it yourself`
   759  
   760  .. code:: bash
   761  
   762      export CORE_PEER_LOCALMSPID="Org1MSP"
   763      export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   764      export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   765      export CORE_PEER_ADDRESS=localhost:7051
   766      peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile  ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble2","yellow","35","tom"]}'
   767      peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile  ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble3","green","20","tom"]}'
   768      peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile  ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble4","purple","20","tom"]}'
   769      peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile  ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble5","blue","40","tom"]}'
   770  
   771  In addition to the arguments for the query in the previous example,
   772  queryMarblesWithPagination adds ``pagesize`` and ``bookmark``. ``PageSize``
   773  specifies the number of records to return per query.  The ``bookmark`` is an
   774  "anchor" telling couchDB where to begin the page. (Each page of results returns
   775  a unique bookmark.)
   776  
   777  *  ``queryMarblesWithPagination``
   778  
   779    Name of the function in the Marbles chaincode. Notice a `shim <https://godoc.org/github.com/hyperledger/fabric-chaincode-go/shim>`__
   780    ``shim.ChaincodeStubInterface`` is used to access and modify the ledger. The
   781    ``getQueryResultForQueryStringWithPagination()`` passes the queryString along
   782    with the pagesize and bookmark to the shim API ``GetQueryResultWithPagination()``.
   783  
   784  .. code:: bash
   785  
   786    func (t *SimpleChaincode) queryMarblesWithPagination(stub shim.ChaincodeStubInterface, args []string) pb.Response {
   787  
   788    	//   0
   789    	// "queryString"
   790    	if len(args) < 3 {
   791    		return shim.Error("Incorrect number of arguments. Expecting 3")
   792    	}
   793  
   794    	queryString := args[0]
   795    	//return type of ParseInt is int64
   796    	pageSize, err := strconv.ParseInt(args[1], 10, 32)
   797    	if err != nil {
   798    		return shim.Error(err.Error())
   799    	}
   800    	bookmark := args[2]
   801  
   802    	queryResults, err := getQueryResultForQueryStringWithPagination(stub, queryString, int32(pageSize), bookmark)
   803    	if err != nil {
   804    		return shim.Error(err.Error())
   805    	}
   806    	return shim.Success(queryResults)
   807    }
   808  
   809  
   810  The following example is a peer command which calls queryMarblesWithPagination
   811  with a pageSize of ``3`` and no bookmark specified.
   812  
   813  .. tip:: When no bookmark is specified, the query starts with the "first"
   814           page of records.
   815  
   816  :guilabel:`Try it yourself`
   817  
   818  .. code:: bash
   819  
   820    // Rich Query with index name explicitly specified and a page size of 3:
   821    peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesWithPagination", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}","3",""]}'
   822  
   823  The following response is received (carriage returns added for clarity), three
   824  of the five marbles are returned because the ``pagsize`` was set to ``3``:
   825  
   826  .. code:: bash
   827  
   828    [{"Key":"marble1", "Record":{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}},
   829     {"Key":"marble2", "Record":{"color":"yellow","docType":"marble","name":"marble2","owner":"tom","size":35}},
   830     {"Key":"marble3", "Record":{"color":"green","docType":"marble","name":"marble3","owner":"tom","size":20}}]
   831    [{"ResponseMetadata":{"RecordsCount":"3",
   832    "Bookmark":"g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkGoOkOWDSOSANIFk2iCyIyVySn5uVBQAGEhRz"}}]
   833  
   834  .. note::  Bookmarks are uniquely generated by CouchDB for each query and
   835             represent a placeholder in the result set. Pass the
   836             returned bookmark on the subsequent iteration of the query to
   837             retrieve the next set of results.
   838  
   839  The following is a peer command to call queryMarblesWithPagination with a
   840  pageSize of ``3``. Notice this time, the query includes the bookmark returned
   841  from the previous query.
   842  
   843  :guilabel:`Try it yourself`
   844  
   845  .. code:: bash
   846  
   847    peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesWithPagination", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}","3","g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkGoOkOWDSOSANIFk2iCyIyVySn5uVBQAGEhRz"]}'
   848  
   849  The following response is received (carriage returns added for clarity).  The
   850  last two records are retrieved:
   851  
   852  .. code:: bash
   853  
   854    [{"Key":"marble4", "Record":{"color":"purple","docType":"marble","name":"marble4","owner":"tom","size":20}},
   855     {"Key":"marble5", "Record":{"color":"blue","docType":"marble","name":"marble5","owner":"tom","size":40}}]
   856    [{"ResponseMetadata":{"RecordsCount":"2",
   857    "Bookmark":"g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkmoKkOWDSOSANIFk2iCyIyVySn5uVBQAGYhR1"}}]
   858  
   859  The final command is a peer command to call queryMarblesWithPagination with
   860  a pageSize of ``3`` and with the bookmark from the previous query.
   861  
   862  :guilabel:`Try it yourself`
   863  
   864  .. code:: bash
   865  
   866      peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesWithPagination", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}","3","g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkmoKkOWDSOSANIFk2iCyIyVySn5uVBQAGYhR1"]}'
   867  
   868  The following response is received (carriage returns added for clarity).
   869  No records are returned, indicating that all pages have been retrieved:
   870  
   871  .. code:: bash
   872  
   873      []
   874      [{"ResponseMetadata":{"RecordsCount":"0",
   875      "Bookmark":"g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkmoKkOWDSOSANIFk2iCyIyVySn5uVBQAGYhR1"}}]
   876  
   877  For an example of how a client application can iterate over
   878  the result sets using pagination, search for the ``getQueryResultForQueryStringWithPagination``
   879  function in the `Marbles sample <https://github.com/hyperledger/fabric-samples/blob/master/chaincode/marbles02/go/marbles_chaincode.go>`__.
   880  
   881  .. _cdb-update-index:
   882  
   883  Update an Index
   884  ~~~~~~~~~~~~~~~
   885  
   886  It may be necessary to update an index over time. The same index may exist in
   887  subsequent versions of the chaincode that gets installed. In order for an index
   888  to be updated, the original index definition must have included the design
   889  document ``ddoc`` attribute and an index name. To update an index definition,
   890  use the same index name but alter the index definition. Simply edit the index
   891  JSON file and add or remove fields from the index. Fabric only supports the
   892  index type JSON. Changing the index type is not supported. The updated
   893  index definition gets redeployed to the peer’s state database when the chaincode
   894  definition is committed to the channel. Changes to the index name or ``ddoc``
   895  attributes will result in a new index being created and the original index remains
   896  unchanged in CouchDB until it is removed.
   897  
   898  .. note:: If the state database has a significant volume of data, it will take
   899            some time for the index to be re-built, during which time chaincode
   900            invokes that issue queries may fail or timeout.
   901  
   902  Iterating on your index definition
   903  ----------------------------------
   904  
   905  If you have access to your peer's CouchDB state database in a development
   906  environment, you can iteratively test various indexes in support of
   907  your chaincode queries. Any changes to chaincode though would require
   908  redeployment. Use the `CouchDB Fauxton interface <http://docs.couchdb.org/en/latest/fauxton/index.html>`__ or a command
   909  line curl utility to create and update indexes.
   910  
   911  .. note:: The Fauxton interface is a web UI for the creation, update, and
   912            deployment of indexes to CouchDB. If you want to try out this
   913            interface, there is an example of the format of the Fauxton version
   914            of the index in Marbles sample. If you have deployed the test network
   915            with CouchDB, the Fauxton interface can be loaded by opening a browser
   916            and navigating to ``http://localhost:5984/_utils``.
   917  
   918  Alternatively, if you prefer not use the Fauxton UI, the following is an example
   919  of a curl command which can be used to create the index on the database
   920  ``mychannel_marbles``:
   921  
   922  .. code:: bash
   923  
   924    // Index for docType, owner.
   925    // Example curl command line to define index in the CouchDB channel_chaincode database
   926     curl -i -X POST -H "Content-Type: application/json" -d
   927            "{\"index\":{\"fields\":[\"docType\",\"owner\"]},
   928              \"name\":\"indexOwner\",
   929              \"ddoc\":\"indexOwnerDoc\",
   930              \"type\":\"json\"}" http://hostname:port/mychannel_marbles/_index
   931  
   932  .. note:: If you are using the test network configured with CouchDB, replace
   933      hostname:port with ``localhost:5984``.
   934  
   935  .. _cdb-delete-index:
   936  
   937  Delete an Index
   938  ~~~~~~~~~~~~~~~
   939  
   940  Index deletion is not managed by Fabric tooling. If you need to delete an index,
   941  manually issue a curl command against the database or delete it using the
   942  Fauxton interface.
   943  
   944  The format of the curl command to delete an index would be:
   945  
   946  .. code:: bash
   947  
   948     curl -X DELETE http://localhost:5984/{database_name}/_index/{design_doc}/json/{index_name} -H  "accept: */*" -H  "Host: localhost:5984"
   949  
   950  
   951  To delete the index used in this tutorial, the curl command would be:
   952  
   953  .. code:: bash
   954  
   955     curl -X DELETE http://localhost:5984/mychannel_marbles/_index/indexOwnerDoc/json/indexOwner -H  "accept: */*" -H  "Host: localhost:5984"
   956  
   957  
   958  
   959  .. Licensed under Creative Commons Attribution 4.0 International License
   960     https://creativecommons.org/licenses/by/4.0/