1

I read in out the documentation on HyperLedger. However, I cannot find any information on storing complex datatypes by that I mean if it is even possible. For instance lets say we have two objects: an author and a book. Is it possible to create a smartcontract that would look like this? (example in typescript) :


export class Book {
    public ISBN: string;
    public Title: string;
}


export class Author {
    public firstName: string;
    public lastName: string;
    public publishedBooks: Array<Book>;
}

And if so how would querying would look like in such instance. On the other hand if it is not possible how would one model such data relations in HyperLedger.

CodeSamurai777
  • 3,285
  • 2
  • 24
  • 42

1 Answers1

2

Yes you can do this. Implement it in the smart contract and use Hyperledger directives to query the ledger.

For example in Go you can use shim PutState and GetState to determine an entity given an ID. If you implement a DB like CouchDB you can even do more complex and rich queries on your database.

[EDIT1] Answer improvement with example: This is how I improved this in my Go Chaincode

type V struct {
    Attribute string `json:"Attribute"`
    Function  string `json:"Function"`
    Value     string `json:"Value"`
}

type AV struct {
    Vs  []V      `json:"Vs"`
    CFs map[string]string `json:"CFs"`
}

As you can see, I am using V struct for an array of Vs. This make my dataset more complex and this is inside the chaincode.

[EDIT 2] Answer improvement with query and put: Adding a new entity is very easy. My examples are always in GoLang. Send a JSON to the chaincode (thanks to the SDK) and next unmarshal it:

var newEntity Entity
json.Unmarshal([]byte(args[0]), &newEntity)

Now use the PutState function to put the new entity given his ID (in my case contained in the JSON file, id field):

entityAsBytes, _ := json.Marshal(newEntity)
err := APIstub.PutState(newEntity.Id, entityAsBytes)

And here you are done. If you now want to query the ledger retrieving that id, you can do:

entityAsByte, err := APIstub.GetState(id)
return shim.Success(entityAsByte)
Riki95
  • 706
  • 1
  • 7
  • 16
  • Could you elaborate. A code example showing putting `Book`s into `Author` class and then retrieving the list of `Book`s for a given author would be great. – CodeSamurai777 Jan 13 '20 at 17:52
  • Just added my Go Code – Riki95 Jan 14 '20 at 09:01
  • Thank you so much. However, as written before could you also add the code for putting elements into this array as well as retrieving them? – CodeSamurai777 Jan 14 '20 at 09:06
  • Added answer to this too. Please upvote and check this as answer if it solved. Best regards – Riki95 Jan 14 '20 at 09:11
  • Yes I understand how putting simple objects work. My question is how would look like putting Books into Author class or in your example putting Vs into AV. And then retrieving Books for a given Author. – CodeSamurai777 Jan 14 '20 at 09:14
  • Also what does `CFs` attribute do? – CodeSamurai777 Jan 14 '20 at 09:16
  • I've just answered you very well. This is not an Hyperledger question anymore but a JSON question now. If you want to add Book into Authors in a JSON is sufficient to do Author: { Book: {} } and next pass it to the chaincode for the unmarshal. If you want to retrieve it next, you should implement a function in your chaincode that is a little bit complex than a normal query. Basically you can retrieve by IDs and next check the secondary indexes to see if you find your book. Otherwise you can implement a more complex database, like Couchdb, and do rich queries – Riki95 Jan 14 '20 at 09:18
  • I will accept your answer but I would be really grateful to see how this as you put it a little bit more complex query would look like. Also please confirm, are you suggesting to keep in the Author class only a list of IDs of Books. To form a kind of foreign key relationship? – CodeSamurai777 Jan 14 '20 at 09:28
  • No you can have not only a list of IDs but a list of objects as I did. – Riki95 Jan 14 '20 at 10:10