区块链笔记(6)-启用CouchDB作为数据库

125 阅读5分钟

前言

1.4版本之后,fabric默认使用CouchDB代替了之前的LevelDB,除了LevelDB支持的键控/合成键/键范围查询之外,CouchDB还支持完整的数据富查询功能,比如针对整个区块链数据的非键查询,因为它的数据内容是以JSON格式存储的,并且是完全可查询的。因此,CouchDB可以满足LevelDB不支持的许多用例的链代码、审计和报告需求

简介

CouchDB是一种NoSQL的解决方案,以键值映射的方式存储文档字段。

它使用JSON,存储数据(文档),使用java脚本作为其查询语言来转换文档,使用http协议为api访问文档,使用Web浏览器查询索引。

安装部署

前面章节已经讲过在启动byfn.sh脚本的时候docker自动拉取所有必须的镜像,当然也就包括了CoucbDB的镜像
若没有也可以用下面命令安装

# docker pull hyperledger/fabric-couchdb:0.4.21

服务启动

fabricCouchDB有两种启动,一种就是普通的docker启动方式,另一种就是使用docker-compose的方式启动,一般而言在fabricCouchDB都是和peer一一对应,因此都是和peer的配置文件写在一起。例如下面这个yaml文件

services: 
  couchdb: 
    container_name: couchdb 
    image: hyperledger/fabric-couchdb:0.4.21 
    ports: 
      - "5984:5984" 
 
  peer0.org1.example.com: 
    container_name: peer0.org1.example.com:1.4.6
    hostname: peer0.org1.example.com 
    image: hyperledger/fabric-peer 
    environment: 
       - CORE_LEDGER_STATE_STATEDATABASE=CouchDB 
       - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984
    #省略后面内容

通过启动Peer服务,一并启动CouchDB,访问地址 http://ip:5984/_utils,页面如下:

各参数说明如下:

名称说明
Databases数据库及数据表的新增,修改等维护管理
Setup配置CouchDB单个peer或多个peer
Active Tasks正在执行的任务
ConfigurationCouchDB的配置参数管理
ReplicationCouchDB数据库的备份管理
DocumentationCouchDB教程
Verify验证服务是否正常进行
Admin Party个人设置

当执行官方案例之后可以发现Peer对应的CouchDB数据库中会生成mychannel_mychannel_lsccmychannel_mycc 3个数据库

mychannel_

保存通道相关的数据

image-20210422115702468

mychannel_lscc

保存系统链码数据

image-20210422115824846

mychannel_mycc

保存用户链码数据,生成a和b的键值对数据

image-20210422115952295

相关接口

检查数据库是否已经安装和运行

# curl http://ip:5984/

若返回以下结果说明已经运行成功

{"couchdb":"Welcome","version":"2.1.1","features":["scheduler"],"vendor":{"name":"The Apache Software Foundation"}}

查询所有数据库列表

curl -X GET http://ip:5984/_all_dbs
#例如
curl -X GET http://192.168.56.103:5984/_all_dbs

返回值如下

["_replicator","_users","mychannel_","mychannel_lscc","mychannel_mycc"]

获取数据库信息

curl -X GET http://ip:5984/数据库名
#例如
curl -X GET http://192.168.56.103:5984/mychannel_

返回值如下

{
    "db_name": "mychannel_", 
    "purge_seq": "0-g1AAAAEzeJzLYWBg4MhgTmHgzcvPy09JdcjLz8gvLskBCjPlsQBJhgdA6j8QZCUy4FV3AKLuPiF1CyDq9hNS1wBRNx-3uqQEIJlUj9dtSQ4gNfH41SiA1NjjVZPIkCQPUZAFAN6AYvY", 
    "update_seq": "8-g1AAAAEzeJzLYWBg4MhgTmHgzcvPy09JdcjLz8gvLskBCjMlMiTJ____PyuRAYeCJAUgmWSPX40DSE08fjUJIDX1eNXksQBJhgYgBVQ2n5C6BRB1-7MSmfGqOwBRd5-QeQ8g6oDuY80CAImSYv4", 
    "sizes": {
        "file": 66801, 
        "external": 9114, 
        "active": 10931
    }, 
    "other": {
        "data_size": 9114
    }, 
    "doc_del_count": 0, 
    "doc_count": 2, 
    "disk_size": 66801, 
    "disk_format_version": 7, 
    "data_size": 10931, 
    "compact_running": false, 
    "cluster": {
        "q": 8, 
        "n": 1, 
        "w": 1, 
        "r": 1
    }, 
    "instance_start_time": "0"
}

获取数据库所有文档

curl -X GET http://ip:5984/数据库名/_all_docs
#例如
curl -X GET http://192.168.56.103:5984/mychannel_/_all_docs

返回值如下:

{
    "total_rows": 2, 
    "offset": 0, 
    "rows": [
        {
            "id": "resourcesconfigtx.CHANNEL_CONFIG_KEY", 
            "key": "resourcesconfigtx.CHANNEL_CONFIG_KEY", 
            "value": {
                "rev": "3-fb17e8d74af2a55232a3d67c5cec1e99"
            }
        }, 
        {
            "id": "statedb_savepoint", 
            "key": "statedb_savepoint", 
            "value": {
                "rev": "5-9cf6b652cc24b4f2c8aa34fa776de685"
            }
        }
    ]
}

查询某个文档

curl -X GET http://ip:5984/数据库名/文档id
#例如
curl -X GET http://192.168.56.103:5984/mychannel_/statedb_savepoint

返回值如下:

{
    "_id": "statedb_savepoint", 
    "_rev": "5-9cf6b652cc24b4f2c8aa34fa776de685", 
    "BlockNum": 4, 
    "TxNum": 0
}

若id值有特殊符号\u0000的格式,则需要这样查询

#错误的查询方式
curl -X GET http://192.168.56.103:5984/mychannel_/mycc\u0000a
#报错信息
{"error":"not_found","reason":"missing"}
#正确的查询方式,把\u0000替换为%00
curl -X GET http://192.168.56.103:5984/mychannel_/mycc%00a

创建数据库

curl -X PUT http://ip:5984/数据库名
#例如
curl -X PUT http://192.168.56.103:5984/test

返回值如下:

{"ok":true}

删除数据库

curl -X DELETE http://ip:5984/数据库名字
#例如
curl -X DELETE http://192.168.56.103:5984/test

返回值如下:

{"ok":true}

添加文档

curl -H "Content-Type:application/json" -X POST http://ip:5984/数据库名 -d'{"_id":"xxx","name":"xxx"}'
#例如
curl -H "Content-Type:application/json" -X POST http://192.168.56.103:5984/test -d'{"_id":"1","name":"hongcb"}'

返回值如下:

{
  "ok": true,
  "id": "1",
  "rev": "1-43e0746f39bf436468609140d71e04c5"
}

修改文档

curl -X PUT http://ip:5984/数据库名/文档id -d '{"_id":"xxx","_rev":"要一致","name":"xxx","title":"xxx"}'
#例如
curl -X PUT http://192.168.56.103:5984/test/1 -d '{"_id":"1","_rev":"1-43e0746f39bf436468609140d71e04c5","name":"hongcb2","title":"hhhh"}'

返回值如下:

{
  "ok": true,
  "id": "1",
  "rev": "2-43c90eac47980abc776ea3fdf6564019"
}

删除文档

curl -X DELETE http://ip:5984/数据库名/文档id?rev=要一致
#例如
curl -X DELETE http://192.168.56.103:5984/test/1?rev=2-43c90eac47980abc776ea3fdf6564019

返回值如下:

{
  "ok": true,
  "id": "1",
  "rev": "3-e7978ecfd4c68ea65cc8098d7815ad9b"
}