本文是学习官网CouchDB中的操作记录,更多详细信息参见官网。
目录
CouchDB Fauxton interface UI界面更新索引
CouchDB Fauxton interface UI界面删除索引
查看索引
启动测试网络
清除网络
[root@localhost ~]# cd /home/gopath/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network #进入test-network目录
[root@localhost test-network]# ./network.sh down #启动网络前先清除网络
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
安装go依赖
[root@localhost test-network]# cd ../chaincode/marbles02/go/ #进入弹珠示例go语言版本目录
[root@localhost go]# GO111MODULE=on go mod vendor #安装go依赖
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 #返回至test-network目录
部署带有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
以上命令创建一个通道mychannel,创建2个peer节点,2个CouchDBa节点,1个排序节点
安装和定义链码
以Org1管理员身份与网络交互
设置环境变量 - Org1身份
[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
打包链码
[root@localhost test-network]# peer lifecycle chaincode package marbles.tar.gz --path ../chaincode/marbles02/go --lang golang --label marbles_1
test-network生成弹珠链码包
安装链码包
[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
查看链码包ID(Package ID)
[root@localhost test-network]# peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: marbles_1:71607ed5ee500dc40b3a413c0f3717c35eca85e94f4e68a089bb71c56618c699, Label: marbles_1
为链码包ID设置一个环境变量
[root@localhost test-network]# export CC_PACKAGE_ID=marbles_1:71607ed5ee500dc40b3a413c0f3717c35eca85e94f4e68a089bb71c56618c699
Org1同意链码定义
[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
以Org2管理员身份与网络交互
设置环境变量 - Org2身份
[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同意链码定义
[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
提交链码至通道
[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
调用链码初始化函数
[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
验证部署的索引
打开一个新终端窗囗
[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]
查询 CouchDB状态数据库
以Org1管理员身份与网络交互
设置环境变量 - Org1身份
[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
创建一个marble(拥有者是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
指定索引查询
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}}]
以上参数含义详见参考文档
查询和索引的最佳实践
写查询的时候记得以下几点:
1. 使用的索引中所有字段必须包含在选择器和排序部分
2. 越复杂的查询性能越低并且使用索引的几率也越低
3. 应该尽量避免引起全表查询 或 全索引查询的操作符,如$or, $in, $regex等
查询添加非索引字段
[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\"]}"]}'
[]
能够使用到索引字段,查询会另外在索引数据中查找符合非索引字段的数据,导致时间变长。
没有包含全部索引字段的查询
[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}}]
将会查询整个数据库,因为索引indexOwnerDoc包含两个字段owner与docType,而查询语句只使用了owner没有使用docType,因此不会使用索引。
复杂查询使用索引
[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}}]
使用条件$or查询会搜索第一个marble和第一条拥有者是tom的数据,它会使用索引,但$or需要扫描索引中的所有项,导致时间变长。
复杂查询不使用索引
[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}}]
CouchDB状态数据库查询中使用分页
创建4个marble(所有者为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
查询每页3条记录
[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"}}]
返回的bookmark是CouchDB每次查询唯一生成的,并显示在结果集中。将返回的bookmark传递给迭代查询的子集中来获取结果的下一个集合(下一页)。
查询下一页
参数bookmark是前一次查询返回的结果
[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"}}]
升级索引
CouchDB Fauxton interface UI界面更新索引
登录用户名密码默认为 admin / adminpw
通过 curl命令更新索引(未成功)
[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."}
删除索引
CouchDB Fauxton interface UI界面删除索引
使用curl命令(未成功)
[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."}
参考文档