2017-03-08 65 views
0

我是新来的区块链和使用hyperledger结构(现在v:0.6)创建一个学习视角的应用程序。通过价值获取世界状态

我保持上blockchain金融交易的台账,一旦交易发生(A基于网络的组件通知上交易的发生,并调用chaincode)。

交易的结构看起来是这样的:

type Transactions struct { 
    ReferenceNumber string `json:"ReferenceNumber"` 
    BillNumber string `json:"BillNumber"` 
    BillingCompany string `json:"BillingCompany"` 
    Amount string `json:"Amount"` 
    Status string `json:"Status"` 
} 

我JSON元帅这个并将其保存与ReferenceNumber陈述的关键。现在

我可以ReferenceNumber的基础上,充分利用国家的事务。但是如果我想根据我们说'状态'这个基础来从国家那里获得交易,那么账单上有多少交易的状态就是'对账'。

有什么办法来查询状态不是关键,但价值的基础上?

回答

1

Worldstate级别的存储在{key,value}级别工作。显而易见,它仅用于指定键的单个值查找。我认为你正在寻找的是要求更高一级的WorldState抽象 - 称为表结构。 布/例子/ chaincode /去/ asset_management_interactive/asset_management.go对如何创建一个表,你想列一个例子。 在定义数据结构的主键以保存事务时,可以将Status包括为其中一个键,并且您还可以根据Status检索数据

一些示例代码以创建表是如下

func createTableTwo(stub shim.ChaincodeStubInterface) error { 
    var columnDefsTableTwo []*shim.ColumnDefinition 
    columnOneTableTwoDef := shim.ColumnDefinition{Name: "colOneTableTwo", 
     Type: shim.ColumnDefinition_STRING, Key: true} 
    columnTwoTableTwoDef := shim.ColumnDefinition{Name: "colTwoTableTwo", 
     Type: shim.ColumnDefinition_INT32, Key: false} 
    columnThreeTableTwoDef := shim.ColumnDefinition{Name: "colThreeTableThree", 
     Type: shim.ColumnDefinition_INT32, Key: true} 
    columnFourTableTwoDef := shim.ColumnDefinition{Name: "colFourTableFour", 
     Type: shim.ColumnDefinition_STRING, Key: true} 
    columnDefsTableTwo = append(columnDefsTableTwo, &columnOneTableTwoDef) 
    columnDefsTableTwo = append(columnDefsTableTwo, &columnTwoTableTwoDef) 
    columnDefsTableTwo = append(columnDefsTableTwo, &columnThreeTableTwoDef) 
    columnDefsTableTwo = append(columnDefsTableTwo, &columnFourTableTwoDef) 
    return stub.CreateTable("tableTwo", columnDefsTableTwo) 
} 

现在将数据插入到该表中,如图

if len(args) < 4 { 
      return nil, errors.New("insertRowTableTwo failed. Must include 4 column values") 
     } 

     col1Val := args[0] 
     col2Int, err := strconv.ParseInt(args[1], 10, 32) 
     if err != nil { 
      return nil, errors.New("insertRowTableTwo failed. arg[1] must be convertable to int32") 
     } 
     col2Val := int32(col2Int) 
     col3Int, err := strconv.ParseInt(args[2], 10, 32) 
     if err != nil { 
      return nil, errors.New("insertRowTableTwo failed. arg[2] must be convertable to int32") 
     } 
     col3Val := int32(col3Int) 
     col4Val := args[3] 

     var columns []*shim.Column 
     col1 := shim.Column{Value: &shim.Column_String_{String_: col1Val}} 
     col2 := shim.Column{Value: &shim.Column_Int32{Int32: col2Val}} 
     col3 := shim.Column{Value: &shim.Column_Int32{Int32: col3Val}} 
     col4 := shim.Column{Value: &shim.Column_String_{String_: col4Val}} 
     columns = append(columns, &col1) 
     columns = append(columns, &col2) 
     columns = append(columns, &col3) 
     columns = append(columns, &col4) 

     row := shim.Row{Columns: columns} 
     ok, err := stub.InsertRow("tableTwo", row) 
     if err != nil { 
      return nil, fmt.Errorf("insertRowTableTwo operation failed. %s", err) 
     } 
     if !ok { 
      return nil, errors.New("insertRowTableTwo operation failed. Row with given key already exists") 
     } 

现在通过不指定所有的键来查询该数据,做如下

if len(args) < 1 { 
      return nil, errors.New("getRowsTableTwo failed. Must include at least key values") 
     } 

     var columns []shim.Column 

     col1Val := args[0] 
     col1 := shim.Column{Value: &shim.Column_String_{String_: col1Val}} 
     columns = append(columns, col1) 

     if len(args) > 1 { 
      col2Int, err := strconv.ParseInt(args[1], 10, 32) 
      if err != nil { 
       return nil, errors.New("getRowsTableTwo failed. arg[1] must be convertable to int32") 
      } 
      col2Val := int32(col2Int) 
      col2 := shim.Column{Value: &shim.Column_Int32{Int32: col2Val}} 
      columns = append(columns, col2) 
     } 

     rowChannel, err := stub.GetRows("tableTwo", columns) 
     if err != nil { 
      return nil, fmt.Errorf("getRowsTableTwo operation failed. %s", err) 
     } 

     var rows []shim.Row 
     for { 
      select { 
      case row, ok := <-rowChannel: 
       if !ok { 
        rowChannel = nil 
       } else { 
        rows = append(rows, row) 
       } 
      } 
      if rowChannel == nil { 
       break 
      } 
     } 

     jsonRows, err := json.Marshal(rows) 
     if err != nil { 
      return nil, fmt.Errorf("getRowsTableTwo operation failed. Error marshaling JSON: %s", err) 
     } 

     return jsonRows, nil 

一旦你插入的数据,该API 存根.GetRows(“tableTwo”,列)可让您检索它,而无需指定所有关键列。

上面的代码是从存在于早些时候在以下路径格里特布料GitHub库文件引用/ src目录/ github.com/hyperledger /面料/ bddtests/chaincode /去/表/ table.go

希望这有助于。

+0

谢谢@Ashishkel这样的详细解释。我现在正在使用表格来解决问题。我设置了2列(ReferenceNumber和Status)作为键列,现在当我使用2个参数进行查询时,将返回表结果,但是当我用2个参数中的任何一个进行查询时,查询无法返回任何行。 我使用的代码与gerrit/src/github.com/hyperledger/fabric/bddtests/chaincode/go/table/table.go –

+0

中描述的一样,可能是当前版本存在问题。我注意到的是,假设你有键A,B(按照相同顺序指定),然后GetRows在我没有指定键时以及指定A时工作。当我单独指定B时,它不起作用。尝试一下。如果你遇到的是同一个问题,那么这是继续前进的一种方式。 – Ashishkel

+0

确切地说,它根本没有任何参数,所有的键或第一个键。我必须扭转密钥的顺序才能创建一个解决方案。尽管非常感谢你的帮助。干杯。 –