Composite keys

We often need to store multiple instances of one type on the ledger, such as multiple trade agreements, letters of credit, and so on. In this case, the keys of those instances will be typically constructed from a combination of attributes—for example, "Trade" + ID, yielding ["Trade1","Trade2", ...]. The key of an instance can be customized in the code, or API functions can be provided in SHIM to construct a composite key (in other words, a unique key) of an instance based on a combination of several attributes. These functions simplify composite key construction. Composite keys can then be used just as a normal string key is used to record and retrieve values using the PutState() and GetState() functions.

The following snippet shows a list of functions that create and work with composite keys:

// The function creates a key by combining the attributes into a single string. 
// The arguments must be valid utf8 strings and must not contain U+0000 (nil byte) and U+10FFFF charactres. 
func CreateCompositeKey(objectType string, attributes []string) (string, error) 
 
// The function splits the compositeKey into attributes from which the key was formed. 
// This function is useful for extracting attributes from keys returned by range queries. 
func SplitCompositeKey(compositeKey string) (string, []string, error) 

In the following snippet we can see a function getTradeKey, which constructs a unique composite key of a trade agreement by combining the keyword Trade with an ID of the trade:

func getTradeKey(stub shim.ChaincodeStubInterface, tradeID string) (string, error) { 
   tradeKey, err := stub.CreateCompositeKey("Trade", []string{tradeID}) 
   if err != nil { 
         return "", err 
   } else { 
         return tradeKey, nil 
   } 
}

In more complex scenarios, keys can be constructed from multiple attributes. Composite keys also allow you to search for assets based on components of the key in range queries. We will explore searching in more detail in the upcoming sections.