存证溯源案例4.0概览
本文分享如何使用 Go
语言和Fabric 2.0链码
开发fabric智能合约实战案例-存证溯源案例,本篇主要介绍链码中富查询使用方法及案例应用。如下图所示:
链码提供以下两个接口来用于富查询:
GetQueryResult(query string) (StateQueryIteratorInterface, error)
GetQueryResultWithPagination(query string, pageSize int32,
bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)
其中前者用于单记录查询,后者用于范围查询。
1、富查询
GetQueryResult(query string) (StateQueryIteratorInterface, error)
存证溯源案例实际应用:
func (s *SmartContract) QueryAssetsByColor(ctx contractapi.TransactionContextInterface, color string) (*Asset, error) {
queryString := fmt.Sprintf(`{"selector":{"docType":"asset","color":"%s"}}`, color)
return getQueryResultForQueryString(ctx, queryString)
}
func getQueryResultForQueryString(ctx contractapi.TransactionContextInterface, queryString string) (*Asset, error) {
resultIterator, err := ctx.GetStub().GetQueryResult(queryString)
if err != nil {
return nil, err
}
defer resultIterator.Close()
if resultIterator.HasNext(){
queryresult, err := resultIterator.Next()
if err != nil {
return nil, err
}
var asset Asset
err = json.Unmarshal(queryresult.Value, &asset)
if err != nil {
return nil, err
}
return &asset, nil
}
return nil, err
}
2、富查询范围查询
GetQueryResultWithPagination(query string, pageSize int32,
bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)
存证溯源案例实际应用:
// 常规无索引范围富查询Color
func (s *SmartContract) QueryAssetsByColor(ctx contractapi.TransactionContextInterface, color string) ([]*Asset, error) {
queryString := fmt.Sprintf(`{"selector":{"docType":"asset","color":"%s"}}`, color)
return getQueryResultForQueryString(ctx, queryString)
}
// 常规无索引范围富查询案例
func (s *SmartContract) QueryAssets(ctx contractapi.TransactionContextInterface, queryString string) ([]*Asset, error) {
return getQueryResultForQueryString(ctx, queryString)
}
func constructQueryResponseFromIterator(resultIterator shim.StateQueryIteratorInterface) ([]*Asset, error) {
var assets []*Asset
for resultIterator.HasNext() {
queryresult, err := resultIterator.Next()
if err != nil {
return nil, err
}
var asset Asset
err = json.Unmarshal(queryresult.Value, &asset)
if err != nil {
return nil, err
}
assets = append(assets, &asset)
}
return assets, nil
}
func getQueryResultForQueryString(ctx contractapi.TransactionContextInterface, queryString string) ([]*Asset, error) {
resultsIterator, err := ctx.GetStub().GetQueryResult(queryString)
if err != nil {
return nil, err
}
defer resultsIterator.Close()
return constructQueryResponseFromIterator(resultsIterator)
}
3、索引富查询
存证溯源案例实际应用:
// 常规使用索引富查询案例
func (s *SmartContract) QueryAssetsByColorIndex(ctx contractapi.TransactionContextInterface, color string) ([]*Asset, error) {
coloredAssetResultsIterator, err := ctx.GetStub().GetStateByPartialCompositeKey(colorIdIndex, []string{color})
if err != nil {
return nil, err
}
defer coloredAssetResultsIterator.Close()
var assets []*Asset
for coloredAssetResultsIterator.HasNext() {
responseRange, err := coloredAssetResultsIterator.Next()
if err != nil {
return nil, err
}
_, compositKeyParts, err := ctx.GetStub().SplitCompositeKey(responseRange.Key)
if err != nil {
return nil, err
}
if len(compositKeyParts) > 1 {
returnedAssetID := compositKeyParts[1]
returnedAssetIDInteger, err := strconv.Atoi(returnedAssetID)
if err != nil {
return nil, err
}
asset, err := s.ReadAsset(ctx, returnedAssetIDInteger)
if err != nil {
return nil, err
}
assets = append(assets, asset)
}
}
return assets, nil
}
4、结论
富查询无需使用索引,但使用索引的查询会更有效率