This article is to learn the operation records in the official website CouchDB. For more details, see Official website.
catalogue
Deploy test network with CouchDB
Install and define chain codes
Interact with the network as an Org1 administrator
Set environment variable - Org1 identity
Set an environment variable for the chain code package ID
Org1 agrees with the chain code definition
Interact with the network as an Org2 administrator
Set environment variable - Org2 identity
Org2 agrees with the chain code definition
Call chain code initialization function
Verify the index of the deployment
Interact with the network as an Org1 administrator
Set environment variable - Org1 identity
Create a marble (owned by tom)
Best practices for querying and indexing
Add non indexed fields to query
There are no queries that contain all index fields
Complex queries do not use indexes
Using paging in CouchDB state database queries
Create 4 marble s (owned by tom)
CouchDB Fauxton interface UI update index
Update index with curl command (unsuccessful)
CouchDB Fauxton interface UI delete index
Use curl command (unsuccessful)
View index
Start test network
Clear network
[root@localhost ~]# cd /home/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network #Enter the test network directory [root@localhost test-network]# ./network.sh down #Clear the network before starting the network Stopping network Stopping cli ... done Stopping peer0.org2.example.com ... done Stopping peer0.org1.example.com ... done Stopping couchdb1 ... done Stopping couchdb0 ... done Stopping orderer.example.com ... done Removing cli ... done Removing peer0.org2.example.com ... done Removing peer0.org1.example.com ... done Removing couchdb1 ... done Removing couchdb0 ... done Removing orderer.example.com ... done Removing network fabric_test Removing volume docker_orderer.example.com Removing volume docker_peer0.org1.example.com Removing volume docker_peer0.org2.example.com WARNING: The DOCKER_SOCK variable is not set. Defaulting to a blank string. Removing network fabric_test WARNING: Network fabric_test not found. Removing volume docker_peer0.org3.example.com WARNING: Volume docker_peer0.org3.example.com not found. Removing remaining containers Removing generated chaincode docker images Untagged: dev-peer0.org2.example.com-marblespv1-e8c33426e02c5397914aa0cee6b3220d7fc519845b5d9e55ad50271d7c87859d-dfd5e9b784e8747e7daecb41865637602411aca0309ec9686e4b0eca5f106ebc:latest Deleted: sha256:be892235a36f87afb91198e3039df8a39a64fe13ffb8120758940fa85b646972 Deleted: sha256:463573b7ee109461596d64f4516f469fe444dd8c85bc165a28effc66dfeb07f1 Deleted: sha256:16ffabd8dbf27909c8bcae34f383707c9744a10e4d8d84ee4813dfa941373de2 Deleted: sha256:1df19494626411ec5459d7ba136842a7ac610ad7cfdb0b9e3cf7257686652765 Untagged: dev-peer0.org1.example.com-marblespv1-e8c33426e02c5397914aa0cee6b3220d7fc519845b5d9e55ad50271d7c87859d-d725be598e16b69a278b15b252cf04436b2c0e4213b23b2a497ab278a73b48a1:latest Deleted: sha256:f14c52e4d0e919cc24710545a9c2ba48228ebdbbd112c13f47ea20407c925e87 Deleted: sha256:5ba362d2a9e9be0b06bcbb3d8dd5966936eea396c3dfeac7b758488aa7ba9770 Deleted: sha256:6311794ae5d7cd6206dc9aa51b3b37e9fbfe36667c9f94b52f6d26f0f712555c Deleted: sha256:e4df66efcd3be1a5eced730714d5f75a81a477769faf1c137a28e61464ad15f7
Install go dependency
[root@localhost test-network]# cd ../chaincode/marbles02/go/ #Enter the pinball sample go language version directory [root@localhost go]# GO111MODULE=on go mod vendor #Install go dependency go: downloading github.com/hyperledger/fabric-chaincode-go v0.0.0-20190823162523-04390e015b85 go: downloading github.com/hyperledger/fabric-protos-go v0.0.0-20190821214336-621b908d5022 go: downloading golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 go: downloading google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 go: downloading golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a [root@localhost go]# cd ../../../test-network #Return to the test network directory
Deploy test network with CouchDB
[root@localhost test-network]# ./network.sh up createChannel -s couchdb [root@localhost test-network]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 330553018a32 hyperledger/fabric-tools:latest "/bin/bash" About a minute ago Up About a minute cli aca027a8ed1d hyperledger/fabric-peer:latest "peer node start" About a minute ago Up About a minute 0.0.0.0:9051->9051/tcp, :::9051->9051/tcp, 7051/tcp, 0.0.0.0:19051->19051/tcp, :::19051->19051/tcp peer0.org2.example.com f69fde856da3 hyperledger/fabric-peer:latest "peer node start" About a minute ago Up About a minute 0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:17051->17051/tcp, :::17051->17051/tcp peer0.org1.example.com 8cc4654cb9a8 couchdb:3.1.1 "tini -- /docker-ent..." About a minute ago Up About a minute 4369/tcp, 9100/tcp, 0.0.0.0:7984->5984/tcp, :::7984->5984/tcp couchdb1 8694494e392e couchdb:3.1.1 "tini -- /docker-ent..." About a minute ago Up About a minute 4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp, :::5984->5984/tcp couchdb0 5f1ab35563bf hyperledger/fabric-orderer:latest "orderer" About a minute ago Up About a minute 0.0.0.0:7050->7050/tcp, :::7050->7050/tcp, 0.0.0.0:7053->7053/tcp, :::7053->7053/tcp, 0.0.0.0:17050->17050/tcp, :::17050->17050/tcp orderer.example.com
The above commands create a channel mychannel, 2 peer nodes, 2 CouchDBa nodes and 1 sorting node
Install and define chain codes
Interact with the network as an Org1 administrator
Set environment variable - Org1 identity
[root@localhost test-network]# export PATH=${PWD}/../bin:$PATH [root@localhost test-network]# export FABRIC_CFG_PATH=${PWD}/../config/ [root@localhost test-network]# export CORE_PEER_TLS_ENABLED=true [root@localhost test-network]# export CORE_PEER_LOCALMSPID="Org1MSP" [root@localhost test-network]# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt [root@localhost test-network]# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp [root@localhost test-network]# export CORE_PEER_ADDRESS=localhost:7051
Packing chain code
[root@localhost test-network]# peer lifecycle chaincode package marbles.tar.gz --path ../chaincode/marbles02/go --lang golang --label marbles_1
Test network generates marbles chain code package
Install chain code package
[root@localhost test-network]# peer lifecycle chaincode install marbles.tar.gz 2021-11-08 01:23:42.311 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJmarbles_1:71607ed5ee500dc40b3a413c0f3717c35eca85e94f4e68a089bb71c56618c699\022\tmarbles_1" > 2021-11-08 01:23:42.312 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: marbles_1:71607ed5ee500dc40b3a413c0f3717c35eca85e94f4e68a089bb71c56618c699
View chain code Package ID
[root@localhost test-network]# peer lifecycle chaincode queryinstalled Installed chaincodes on peer: Package ID: marbles_1:71607ed5ee500dc40b3a413c0f3717c35eca85e94f4e68a089bb71c56618c699, Label: marbles_1
Set an environment variable for the chain code package ID
[root@localhost test-network]# export CC_PACKAGE_ID=marbles_1:71607ed5ee500dc40b3a413c0f3717c35eca85e94f4e68a089bb71c56618c699
Org1 agrees with the chain code definition
[root@localhost test-network]# export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem [root@localhost test-network]# 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 --cafile $ORDERER_CA 2021-11-08 01:51:35.765 CST [chaincodeCmd] ClientWait -> INFO 001 txid [48d3195bf3812c888bacc12b4747f110356faf65183cd50c78b826e2229fff57] committed with status (VALID) at localhost:7051
Interact with the network as an Org2 administrator
Set environment variable - Org2 identity
[root@localhost test-network]# export CORE_PEER_LOCALMSPID="Org2MSP" [root@localhost test-network]# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt [root@localhost test-network]# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp [root@localhost test-network]# export CORE_PEER_ADDRESS=localhost:9051
Org2 agrees with the chain code definition
[root@localhost test-network]# 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 --cafile $ORDERER_CA 2021-11-08 01:54:43.839 CST [chaincodeCmd] ClientWait -> INFO 001 txid [ffcf7b2ff0ad6e02eab1be835ffb8805384a5ae6f322f9d0cbc7fa7445de3fa2] committed with status (VALID) at localhost:9051
Submit chain code to channel
[root@localhost test-network]# export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem [root@localhost test-network]# export ORG1_CA=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt [root@localhost test-network]# export ORG2_CA=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt [root@localhost test-network]# 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 --cafile $ORDERER_CA --peerAddresses localhost:7051 --tlsRootCertFiles $ORG1_CA --peerAddresses localhost:9051 --tlsRootCertFiles $ORG2_CA 2021-11-08 01:55:54.525 CST [chaincodeCmd] ClientWait -> INFO 001 txid [c1013eaeffdc8996037eb034bdd323f3a5e91dca5fecfbce42afd1db704da37f] committed with status (VALID) at localhost:9051 2021-11-08 01:55:54.643 CST [chaincodeCmd] ClientWait -> INFO 002 txid [c1013eaeffdc8996037eb034bdd323f3a5e91dca5fecfbce42afd1db704da37f] committed with status (VALID) at localhost:7051
Call chain code initialization function
[root@localhost test-network]# peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --isInit --tls --cafile $ORDERER_CA --peerAddresses localhost:7051 --tlsRootCertFiles $ORG1_CA -c '{"Args":["Init"]}' 2021-11-08 01:57:55.127 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
Verify the index of the deployment
Open a new terminal window
[root@localhost ~]# docker logs peer0.org1.example.com 2>&1 | grep "CouchDB index" 2021-11-07 17:55:54.591 UTC [couchdb] createIndex -> INFO 066 Created CouchDB index [indexOwner] in state database [mychannel_marbles] using design document [_design/indexOwnerDoc]
Query CouchDB status database
Interact with the network as an Org1 administrator
Set environment variable - Org1 identity
[root@localhost test-network]# export CORE_PEER_LOCALMSPID="Org1MSP" [root@localhost test-network]# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt [root@localhost test-network]# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp [root@localhost test-network]# export CORE_PEER_ADDRESS=localhost:7051
Create a marble (owned by tom)
[root@localhost test-network]# 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"]}' 2021-11-08 02:15:25.051 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
Specify index query
peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"]}'
[root@localhost test-network]# peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"]}' [{"Key":"marble1", "Record":{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}}]
See the reference document for the meaning of the above parameters
Best practices for querying and indexing
When writing a query, remember the following:
1. All fields in the index used must be included in the selector and sort sections
2. The more complex the query, the lower the performance and the lower the probability of using the index
3. Operators that cause full table query or full index query should be avoided as far as possible, such as $or, $in, $regex, etc
Add non indexed fields to query
[root@localhost test-network]# export CHANNEL_NAME=mychannel [root@localhost test-network]# peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\",\"color\":\"red\"}, \"use_index\":[\"/indexOwnerDoc\", \"indexOwner\"]}"]}' []
If the index field can be used, the query will find the data matching the non index field in the index data, resulting in a longer time.
There are no queries that contain all index fields
[root@localhost test-network]# peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"owner\":\"tom\"}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}' [{"Key":"marble1", "Record":{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}}]
The entire database will be queried because the index indexOwnerDoc contains two fields owner and docType, while the query statement only uses owner and does not use docType, so the index will not be used.
Complex queries use indexes
[root@localhost test-network]# peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"$or\":[{\"docType\":\"marble\"},{\"owner\":\"tom\"}]}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}' [{"Key":"marble1", "Record":{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}}]
Using the condition $or query will search for the first marble and the first data whose owner is tom. It will use the index, but $or needs to scan all items in the index, resulting in a longer time.
Complex queries do not use indexes
[root@localhost test-network]# peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"$or\":[{\"docType\":\"marble\",\"owner\":\"tom\"},{\"color\":\"yellow\"}]}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}' [{"Key":"marble1", "Record":{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}}]
Using paging in CouchDB state database queries
Create 4 marble s (owned by tom)
[root@localhost test-network]# export CORE_PEER_LOCALMSPID="Org1MSP" [root@localhost test-network]# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt [root@localhost test-network]# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp [root@localhost test-network]# export CORE_PEER_ADDRESS=localhost:7051 [root@localhost test-network]# 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"]}' 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"]}' 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"]}' 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"]}'2021-11-08 02:56:20.227 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 [root@localhost test-network]# 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"]}' 2021-11-08 02:56:20.279 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 [root@localhost test-network]# 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"]}' 2021-11-08 02:56:20.334 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 [root@localhost test-network]# 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"]}' 2021-11-08 02:56:21.485 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
Query 3 records per page
[root@localhost test-network]# peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesWithPagination", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}","3",""]}' [{"Key":"marble1", "Record":{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}},{"Key":"marble2", "Record":{"color":"yellow","docType":"marble","name":"marble2","owner":"tom","size":35}},{"Key":"marble3", "Record":{"color":"green","docType":"marble","name":"marble3","owner":"tom","size":20}}][{"ResponseMetadata":{"RecordsCount":"3", "Bookmark":"g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkGoOkOWDSOSANIFk2iCyIyVySn5uVBQAGEhRz"}}]
The returned bookmark is uniquely generated by CouchDB for each query and is displayed in the result set. Pass the returned bookmark to the subset of the iterative query to get the next set of results (next page).
Query next page
The parameter bookmark is the result returned from the previous query
[root@localhost test-network]# peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesWithPagination", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}","3","g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkGoOkOWDSOSANIFk2iCyIyVySn5uVBQAGEhRz"]}' [{"Key":"marble4", "Record":{"color":"purple","docType":"marble","name":"marble4","owner":"tom","size":20}},{"Key":"marble5", "Record":{"color":"blue","docType":"marble","name":"marble5","owner":"tom","size":40}}][{"ResponseMetadata":{"RecordsCount":"2", "Bookmark":"g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkmoKkOWDSOSANIFk2iCyIyVySn5uVBQAGYhR1"}}]
Upgrade index
CouchDB Fauxton interface UI update index
The default login user name and password is admin / adminpw
Update index with curl command (unsuccessful)
[root@localhost test-network]# curl -i -X POST -H "Content-Type: application/json" -d "{\"index\":{\"fields\":[\"docType\",\"owner\"]}, \"name\":\"indexOwner\", \"ddoc\":\"indexOwnerDoc\", \"type\":\"json\"}" http://localhost:5984/mychannel_marbles/_index HTTP/1.1 401 Unauthorized Cache-Control: must-revalidate Connection: close Content-Length: 78 Content-Type: application/json Date: Sun, 07 Nov 2021 19:38:30 GMT Server: CouchDB/3.1.1 (Erlang OTP/20) X-Couch-Request-ID: ad95c901ef X-CouchDB-Body-Time: 0 {"error":"unauthorized","reason":"You are not authorized to access this db."}
Delete index
CouchDB Fauxton interface UI delete index
Use curl command (unsuccessful)
[root@localhost test-network]# curl -X DELETE http://localhost:5984/mychannel_marbles/_index/indexOwnerDoc/json/indexOwner -H "accept: */*" -H "Host: localhost:5984" {"error":"unauthorized","reason":"You are not authorized to access this db."}
Reference documents
Official website: use CouchDB - hyperledger fabricdocs master document