'Hyperledger fabric: Querying implicit data collection
I am seeing this when querying data from implicit private data collection. Please see code snippet below.
When I query individual key (using QueryBidPrivate/GetPrivateData), I get corresponding data. But if I query the complete collection (using GetPrivateDataByRange(collection, "", "")), I get nothing from the Iterator.
peer chaincode query -C mychannel -n govtcontract -c '{"function":"QueryBidPrivate","Args":["100", "1035"]}' {"bidamt":100,"biddate":"2022-05-04","contractid":"1035","salt":"4567ab4567","vendorid":"100"}
peer chaincode query -C mychannel -n govtcontract -c '{"function":"ListAllBids","Args":[]}'
No output
Is there anything I am missing here ?
// ListAllBids returns all Bids details from private state
func (s *SmartContract) ListAllBids(ctx contractapi.TransactionContextInterface) ([]VendorBid, error) {
// Get client org id and verify it matches peer org id.
// In this scenario, client is only authorized to read/write private data from its own peer.
clientOrgID, err := getClientOrgID(ctx, true)
if err != nil {
return nil, fmt.Errorf("failed to get verified OrgID: %s", err.Error())
}
collection := "_implicit_org_" + clientOrgID
BidIterator, err := ctx.GetStub().GetPrivateDataByRange(collection, "", "")
if err != nil {
logger.Infof("ListAllBids error: %s", err.Error())
return nil, fmt.Errorf("failed to read bid list : %s", err.Error())
}
if BidIterator == nil {
logger.Infof("ListAllBids : null iterator ")
return nil, fmt.Errorf("bid private details does not exist ")
}
defer BidIterator.Close()
logger.Infof("ListAllBids in govtcontract: no error")
var allbids []VendorBid
myMSPID, err := ctx.GetClientIdentity().GetMSPID()
logger.Infof("myMSPID: %s", myMSPID)
for BidIterator.HasNext() {
logger.Infof("Iterator has element: ")
entrybid, err := BidIterator.Next()
if err != nil {
return nil, err
}
var bidvar VendorBid
err = json.Unmarshal(entrybid.Value, &bidvar)
if err != nil {
return nil, err
}
allbids = append(allbids, bidvar)
logger.Infof("Iterator element: %s", entrybid.Value)
}
return allbids, nil
}
=========================================
// QueryBidPrivate returns the Bid details from owner's private data collection
func (s *SmartContract) QueryBidPrivate(ctx contractapi.TransactionContextInterface, vendorId string, contractId string) (string, error) {
// Get client org id and verify it matches peer org id.
// In this scenario, client is only authorized to read/write private data from its own peer.
clientOrgID, err := getClientOrgID(ctx, true)
if err != nil {
return "", fmt.Errorf("failed to get verified OrgID: %s", err.Error())
}
collection := "_implicit_org_" + clientOrgID
bidconkey, err := ctx.GetStub().CreateCompositeKey(vendorId, []string{contractId})
bidDetails, err := ctx.GetStub().GetPrivateData(collection, bidconkey)
if err != nil {
return "", fmt.Errorf("failed to read bid private properties from client org's collection: %s", err.Error())
}
if bidDetails == nil {
return "", fmt.Errorf("bid private details does not exist in client org's collection: %s", contractId)
}
return string(bidDetails), nil
}
Solution 1:[1]
I faced the same error in the smart contract. The issue here is because of storing data on the composite key. Instead of below code :
for BidIterator.HasNext() { logger.Infof("Iterator has element: ") entrybid, err := BidIterator.Next() if err != nil { return nil, err } var bidvar VendorBid err = json.Unmarshal(entrybid.Value, &bidvar) if err != nil { return nil, err } allbids = append(allbids, bidvar) logger.Infof("Iterator element: %s", entrybid.Value) }
Use the below function
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("{")
//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
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |