LevelDB是默认的状态数据库.LevelDB是采用C++编写的一种高性能嵌入式数据库,没有独立的数据库进程,占用资源少,速度快。
CouchDB是一种文档型数据库,提供了RESTful的API操作文档,CouchDB支持原生的JSON和字节数组的操作、富查询,尤其是从Fabric1.3版本开始支持分页。
编写节点配置文件及CouchDB配置文件docker-compose-couchdb.yaml
version: '2'
services:
couchdb0:
container_name: couchdb0
image: hyperledger/fabric-couchdb
# Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
# for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode.
environment:
- COUCHDB_USER=
- COUCHDB_PASSWORD=
# Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
# for example map it to utilize Fauxton User Interface in dev environments.
ports:
- "5984:5984"
以上为最简配置,仅包含用户名、密码、端口等信息,更多配置项可查阅相关的资料。启动CouchDB容器:
docker-compose -f ../docker-compose-couchdb.yaml up -d
在peer节点的配置文件中增加以下配置项
- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984
# The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
# provide the credentials for ledger to connect to CouchDB. The username and password must
# match the username and password set for the associated CouchDB.
- CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME
- CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
启动相应容器,OK,基础环境已经完成。
常见shimAPI:Go,node.js, Java
LevelDB和CouchDB都支持基本的shim API:
GetState(key string) ([]byte, error)
PutState(key string, value []byte) error
GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error)
GetStateByPartialCompositeKey(objectType string, keys []string) (StateQueryIteratorInterface, error)
对于CouchDB的富查询,API提供了 GetQueryResult(query string) (StateQueryIteratorInterface, error) 接口,其中参数query string格式参考 CouchDB JSON 查询语法
{
"selector": {
"year": {"$gt": 2010}
},
"fields": ["_id", "_rev", "year", "title"],
"sort": [{"year": "asc"}],
"limit": 2,
"skip": 0,
"execution_stats": true
}
Fabric支持针对富查询、基于范围的查询、分页查询。由于Fabric本身对于查询结果的最大数目进行了限制,因此在CouchDB查询中,不接受CouchDB limit关键字。
分页查询API提供以下三个常见的接口:
GetStateByRangeWithPagination(startKey, endKey string, pageSize int32, bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)
GetStateByPartialCompositeKeyWithPagination(objectType string, keys []string, pageSize int32, bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)
GetQueryResultWithPagination(query string, pageSize int32, bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)
指定查询数量(pageSize )和书签(bookmark ),接口返回数据和下次查询的书签(对于初次查询,书签传入空字符串“”),分页查询是只读的,为了避免查询时间过长,所有的链码查询返回结果数据的最大条数都由core.yaml中的totalQueryLimit(默认值为100000)限定。另外无论是否启用分页,peer都会根据core.yaml中的internalQueryLimit(默认值为1000)分批查询CouchDB,以保障性能。
索引使JSON查询更高效,并且对应排序(sort)而言,创建索引是必须的。使用方法:在链码文件所在目录,创建META-INF / statedb / couchdb / indexes目录,每个索引必须在扩展名为.json的文本文件中定义,遵循CouchDB索引的基本语法. 例如:
{"index":{"fields":["docType","owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"}
当链码实例化时,会自动创建到通道中的节点的状态数据库。索引建立后,链码查询将自动使用索引。 CouchDB可以根据查询中使用的字段自动确定要使用的索引。 另外,在selector查询中,可以使用use_index关键字指定索引。
链码后续版本中可能存在相同的索引, 要更改索引,可使用相同的索引名称,但要更改索引定义。 安装/实例化后,索引定义将重新部署到peer节点的状态数据库。
CouchDB Fauxton interface 是一个WEB UI,支持外部创建索引,更新索引,地址:http://localhost:5984/_utils
应用程序可以通过POST请求,进行索引的创建和删除,这里为了测试方便,我们通过curl进行接口交互.
索引创建(数据库mychannel_marbles):
curl -i -X POST -H "Content-Type: application/json" -d
"{\"index\":{\"fields\":[\"docType\",\"owner\"]},
\"name\":\"indexOwner\",
\"ddoc\":\"indexOwnerDoc\",
\"type\":\"json\"}" http://hostname:port/mychannel_marbles/_index
一般情况数据库命名为通道名_链码名,如上面例子,通道mychannel,链码marbles
索引删除(数据库mychannel_marbles):
curl -X DELETE http://localhost:5984/mychannel_marbles/_index/indexOwnerDoc/json/indexOwner -H "accept: */*" -H "Host: localhost:5984"
命令格式
curl -X DELETE http://localhost:5984/{database_name}/_index/{design_doc}/json/{index_name} -H "accept: */*" -H "Host: localhost:5984"