fabric1.3 新特性 分页查询(CouchDB) 链码事例+调用

 搭建hyperledger fabric 网络(数据库 使用CouchDB )参考上一篇随笔:快速搭建hyperledger fabric 1.3 网络

当CouchDB查询返回大型结果集时,可以使用一系列API,这些API可以通过调用链代码来对结果列表进行分页。 分页提供了一种机制,通过指定页面大小和起始点来划分结果集——一个指示结果集开始位置的书签。 客户端应用程序迭代地调用执行查询的链代码,直到不再返回结果。

main.go

package main

import (
    "fmt"

    "github.com/hyperledger/fabric/core/chaincode/shim"
)

type ChainCode struct {
}

type Msg struct {
    Status bool   `json:"Status"`
    Code   int    `json:"Code"`
    Result string `json:"Result"`
}

func main() {

    err := shim.Start(new(ChainCode))
    if err != nil {
        fmt.Printf("Error starting chaincode: %s", err)
    }
}

router.go

package main

import (
    "fmt"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    pb "github.com/hyperledger/fabric/protos/peer"
)

func (cc *ChainCode) Init(stub shim.ChaincodeStubInterface) pb.Response {

    return shim.Success(nil)
}

func (cc *ChainCode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {

    function, args := stub.GetFunctionAndParameters()
    switch function {
    case "addServiceRecord":
        //新增记录
        return cc.addServiceRecord(stub, args)

    case "getServiceRecord":
        //查询
        return cc.getServiceRecord(stub, args)

    default:
        //error
        fmt.Println("invoke did not find func: " + function)
        return shim.Error("Received unknown function invocation")
    }

}

emr.go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "strconv"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    pb "github.com/hyperledger/fabric/protos/peer"
)

type ServiceRecord struct {
    Frcode           string `json:"frcode"`           //县区代码
    Service_Code     string `json:"service_code"`     //卫生服务活动代码
    Service_Name     string `json:"service_name"`     //卫生服务活动
    Service_Time     string `json:"service_time"`     //活动时间
    Institution_Code string `json:"institution_code"` //医疗机构编号
    Institution_Name string `json:"institution_name"` //医疗机构名称
    OperatorId       string `json:"operatorid"`       //操作人编号
    Operator_Name    string `json:"operator_name"`    //操作人名称
    Operate_Time     string `json:"operate_time"`     //操作时间,年月日+时分秒
    PersonId         string `json:"personid"`         //服务对象编号
    Person_Name      string `json:"person_name"`      //服务对象名称
    ServiceId        string `json:"serviceid"`        //记录编号
    Area_Code        string `json:"area_code"`        //人员所属区域编码
}

func (cc *ChainCode) addServiceRecord(stub shim.ChaincodeStubInterface, args []string) pb.Response {

    jsonStr := args[0]
    var serviceRecord ServiceRecord
    err := json.Unmarshal([]byte(jsonStr), &serviceRecord)
    if err != nil {
        message := "数据处理失败! 参数错误!"
        msg := &Msg{Status: false, Code: 0, Result: message}
        rev, _ := json.Marshal(msg)
        return shim.Success(rev)
    }

    key := serviceRecord.ServiceId
    esixtAsBytes, err := stub.GetState(key)
    if string(esixtAsBytes) != "" || err != nil {
        message := "数据处理失败! 重复的记录编号!"
        msg := &Msg{Status: false, Code: 0, Result: message}
        rev, _ := json.Marshal(msg)
        return shim.Success(rev)
    }

    serviceRecordAsBytes, _ := json.Marshal(serviceRecord)
    err = stub.PutState(key, serviceRecordAsBytes)
    if err != nil {
        message := "数据处理失败! 存储错误!"
        msg := &Msg{Status: false, Code: 0, Result: message}
        rev, _ := json.Marshal(msg)
        return shim.Success(rev)
    }
    message := "数据处理成功!"
    msg := &Msg{Status: true, Code: 0, Result: message}
    rev, _ := json.Marshal(msg)
    return shim.Success(rev)
}

func (cc *ChainCode) getServiceRecord(stub shim.ChaincodeStubInterface, args []string) pb.Response {

    queryString := args[0]
    pageSize, err := strconv.ParseInt(args[1], 10, 32)
    if err != nil {
        message := "数据处理失败! 参数错误!"
        msg := &Msg{Status: false, Code: 0, Result: message}
        rev, _ := json.Marshal(msg)
        return shim.Success(rev)
    }
    bookmark := args[2]

    queryResults, err := getQueryResultForQueryStringWithPagination(stub, queryString, int32(pageSize), bookmark)
    if err != nil {
        message := "查询失败! " + err.Error()
        msg := &Msg{Status: false, Code: 0, Result: message}
        rev, _ := json.Marshal(msg)
        return shim.Success(rev)
    }
    msg := &Msg{Status: true, Code: 0, Result: string(queryResults)}
    rev, _ := json.Marshal(msg)
    return shim.Success(rev)

}

func getQueryResultForQueryStringWithPagination(stub shim.ChaincodeStubInterface, queryString string, pageSize int32, bookmark string) ([]byte, error) {

    fmt.Printf("- getQueryResultForQueryString queryString:\n%s\n", queryString)

    resultsIterator, responseMetadata, err := stub.GetQueryResultWithPagination(queryString, pageSize, bookmark)
    if err != nil {
        return nil, err
    }
    defer resultsIterator.Close()

    buffer, err := constructQueryResponseFromIterator(resultsIterator)
    if err != nil {
        return nil, err
    }

    bufferWithPaginationInfo := addPaginationMetadataToQueryResults(buffer, responseMetadata)

    fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", bufferWithPaginationInfo.String())

    return buffer.Bytes(), nil
}

func constructQueryResponseFromIterator(resultsIterator shim.StateQueryIteratorInterface) (*bytes.Buffer, error) {
    // buffer is a JSON array containing QueryResults
    var buffer bytes.Buffer
    buffer.WriteString("[")

    bArrayMemberAlreadyWritten := false
    for resultsIterator.HasNext() {
        queryResponse, err := resultsIterator.Next()
        if err != nil {
            return nil, err
        }
        // Add a comma before array members, suppress it for the first array member
        if bArrayMemberAlreadyWritten == true {
            buffer.WriteString(",")
        }
        buffer.WriteString("{\"Key\":")
        buffer.WriteString("\"")
        buffer.WriteString(queryResponse.Key)
        buffer.WriteString("\"")

        buffer.WriteString(", \"Record\":")
        // Record is a JSON object, so we write as-is
        buffer.WriteString(string(queryResponse.Value))
        buffer.WriteString("}")
        bArrayMemberAlreadyWritten = true
    }
    buffer.WriteString("]")

    return &buffer, nil
}

func addPaginationMetadataToQueryResults(buffer *bytes.Buffer, responseMetadata *pb.QueryResponseMetadata) *bytes.Buffer {

    buffer.WriteString("[{\"ResponseMetadata\":{\"RecordsCount\":")
    buffer.WriteString("\"")
    buffer.WriteString(fmt.Sprintf("%v", responseMetadata.FetchedRecordsCount))
    buffer.WriteString("\"")
    buffer.WriteString(", \"Bookmark\":")
    buffer.WriteString("\"")
    buffer.WriteString(responseMetadata.Bookmark)
    buffer.WriteString("\"}}]")

    return buffer
}
View Code

安装合约
peer chaincode install -n emr -v 1.0 -l golang -p github.com/chaincode/EMR/go/

实例化合约
peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel -n emr -l golang -v 1.0 -c '{"Args":["init",""]}' -P 'OR ('\''Org1MSP.peer'\'','\''Org2MSP.peer'\'')'

插入数据1
peer chaincode invoke -C mychannel -n emr -c '{"Args":["addServiceRecord","{\"Frcode\":\"xxxx002\",\"Service_Code\":\"xxxx\",\"Service_Name\":\"1\",\"Service_Time\":\"xxxx\",\"Institution_Code\":\"xxxx\",\"Institution_Name\":\"198544455454\",\"OperatorId\":\"xxxxx\",\"Operator_Name\":\"0\",\"Operate_Time\":\"xxxxx\",\"PersonId\":\"xxxxx\",\"Person_Name\":\"xxxxx\",\"ServiceId\":\"xxxxx001\",\"Area_Code\":\"xxxxx\"}"]}' --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

插入数据2
peer chaincode invoke -C mychannel -n emr -c '{"Args":["addServiceRecord","{\"Frcode\":\"xxxx002\",\"Service_Code\":\"xxxx\",\"Service_Name\":\"1\",\"Service_Time\":\"xxxx\",\"Institution_Code\":\"xxxx\",\"Institution_Name\":\"198544455454\",\"OperatorId\":\"xxxxx\",\"Operator_Name\":\"0\",\"Operate_Time\":\"xxxxx\",\"PersonId\":\"xxxxx\",\"Person_Name\":\"xxxxx\",\"ServiceId\":\"xxxxx002\",\"Area_Code\":\"xxxxx\"}"]}' --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

插入数据3
peer chaincode invoke -C mychannel -n emr -c '{"Args":["addServiceRecord","{\"Frcode\":\"xxxx002\",\"Service_Code\":\"xxxx\",\"Service_Name\":\"1\",\"Service_Time\":\"xxxx\",\"Institution_Code\":\"xxxx\",\"Institution_Name\":\"198544455454\",\"OperatorId\":\"xxxxx\",\"Operator_Name\":\"0\",\"Operate_Time\":\"xxxxx\",\"PersonId\":\"xxxxx\",\"Person_Name\":\"xxxxx\",\"ServiceId\":\"xxxxx003\",\"Area_Code\":\"xxxxx\"}"]}' --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

插入数据4
peer chaincode invoke -C mychannel -n emr -c '{"Args":["addServiceRecord","{\"Frcode\":\"xxxx002\",\"Service_Code\":\"xxxx\",\"Service_Name\":\"1\",\"Service_Time\":\"xxxx\",\"Institution_Code\":\"xxxx\",\"Institution_Name\":\"198544455454\",\"OperatorId\":\"xxxxx\",\"Operator_Name\":\"0\",\"Operate_Time\":\"xxxxx\",\"PersonId\":\"xxxxx\",\"Person_Name\":\"xxxxx\",\"ServiceId\":\"xxxxx004\",\"Area_Code\":\"xxxxx\"}"]}' --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

插入数据5
peer chaincode invoke -C mychannel -n emr -c '{"Args":["addServiceRecord","{\"Frcode\":\"xxxx002\",\"Service_Code\":\"xxxx\",\"Service_Name\":\"1\",\"Service_Time\":\"xxxx\",\"Institution_Code\":\"xxxx\",\"Institution_Name\":\"198544455454\",\"OperatorId\":\"xxxxx\",\"Operator_Name\":\"0\",\"Operate_Time\":\"xxxxx\",\"PersonId\":\"xxxxx\",\"Person_Name\":\"xxxxx\",\"ServiceId\":\"xxxxx005\",\"Area_Code\":\"xxxxx\"}"]}' --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

分页查询1(如果未指定书签,则查询以“第一”记录页开头。)
peer chaincode query -C mychannel -n emr -c '{"Args":["getServiceRecord","{\"selector\":{\"$and\": [{\"frcode\":\"xxxx002\"},{\"service_code\":\"xxxx\"}]}}","3",""]}'

分页查询2
peer chaincode query -C mychannel -n emr -c '{"Args":["getServiceRecord","{\"selector\":{\"$and\": [{\"frcode\":\"xxxx002\"},{\"service_code\":\"xxxx\"}]}}","3","g1AAAABAeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYpzVICAgYExSJ4DJo8ikwUAQs8Smw"]}'

分页查询3
peer chaincode query -C mychannel -n emr -c '{"Args":["getServiceRecord","{\"selector\":{\"$and\": [{\"frcode\":\"xxxx002\"},{\"service_code\":\"xxxx\"}]}}","3","g1AAAABAeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYpzVICAgYEpSJ4DJo8ikwUAQwsSnw"]}'

 

转载于:https://www.cnblogs.com/falsh/p/9947767.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值