Hyperledger Fabric 的复合键是基于多个列组合成一个复合键,并基于复合键存数据,基于复合键或部分列快速取数据。复合键将会使用复合键的类型名及多个列数据、"\u0000"生成实际使用的Key。
示例:
CreateCompositeKey("id~version~min~sub", []string{"1","1","3","1"})
类型名:id~version~min~sub
参数:id:1,version:1,min:3,sub:1
生成的复合键是:"\u0000id~version~min~sub\u00001\u00001\u00003\u00001\u0000"
主要函数介绍
①创建复合键CreateCo
CreateCompositeKey(objectType string, attributes []string) (string, error)
参数:
objectType 复合键类型名
attributes 复合键使用子键
返回值:(复合键,异常)
②基于复合键查询
GetStateByPartialCompositeKey(objectType string, keys []string) (StateQueryIteratorInterface, error)
参数:
objectType 复合键类型名
keys 查询使用的子键集合(必须是根据创建复合键的顺序添加部门子键,不能基于后面的子键查询)
返回值:(查询结果迭代器,异常)
③拆分键
SplitCompositeKey(compositeKey string) (string, []string, error)
参数:
compositeKey 复合键
返回值:(复合键类型名,包含的子键,异常)
④页查询
GetStateByPartialCompositeKeyWithPagination(objectType string, keys []string,
pageSize int32, bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)
参数:
objectType 复合键类型名
keys 查询使用的子键集合
pageSize 查询页大小
bookmark 书签
返回值:
StateQueryIteratorInterface 返回内容的迭代器
QueryResponseMetadata 两个中重要属性,①本次返回对象数量②下一个对象的复合主键
书签为空时,返回基于objectType、keys查询结果的前pagesize个。
书签不为空时,返回集的第一个值的key是书签的值
示例:
①生成复合键,并已复合键存储数据
func (t *TestChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 3 {
shim.Error(ParamNumerNotFit)
}
id, version, minorversion, subversion, content := args[0], args[1], args[2], args[3], args[4]
key, err := stub.CreateCompositeKey(TypeName, []string{id, version, minorversion, subversion})
if err != nil {
return shim.Error(err.Error())
}
user := User{id, version, minorversion, subversion, content}
bUser, err := json.Marshal(user)
stub.PutState(key, bUser)
return shim.Success(nil)
}
②根据子键查询,并解析复合键
func (t *TestChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 1 {
shim.Error(ParamNumerNotFit)
}
queryResult, _ := stub.GetStateByPartialCompositeKey(TypeName, []string{args[0]})
for queryResult.HasNext() {
t, _ := queryResult.Next()
key := t.GetKey()
typeName, keyList, _ := stub.SplitCompositeKey(key)
fmt.Println(typeName)
fmt.Println(keyList)
}
bUserList := parseQueryResult(queryResult)
return shim.Success(bUserList)
}
③页查询
func (t *TestChaincode) queryPage(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var mark = ""
if len(args) != 2 && len(args) != 3 {
shim.Error(ParamNumerNotFit)
}
if len(args) == 3 {
mark = args[2]
}
queryResult, metadata, _ := stub.GetStateByPartialCompositeKeyWithPagination(TypeName, args[:2], 2, mark)
bUserList := parseQueryResult(queryResult)
count := metadata.GetFetchedRecordsCount()
nextmark := metadata.GetBookmark()
var result = map[string]string{}
result["data"] = string(bUserList)
result["count"] = string(count)
result["nextmark"] = nextmark
bresult, _ := json.Marshal(result)
return shim.Success(bresult)
}