2017-03-08 96 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

確切地說,它根本沒有任何參數,所有的鍵或第一個鍵。我必須扭轉密鑰的順序才能創建一個解決方案。儘管非常感謝你的幫助。乾杯。 –