Сортировка не работает в ткани с гиперлипером golang chaincode - PullRequest
0 голосов
/ 25 марта 2019

Я пытаюсь отсортировать результат в цепочке кодов Голанга, но результат случайный, ниже приведен пример цепочки кодов:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "time"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/protos/peer"
)

type itemStruct struct {
    ID        string    `json:"id"`
    Status    string    `json:"status"`
    CreatedAt time.Time `json:"created_at"`
}

func createItem(stub shim.ChaincodeStubInterface, args []string) peer.Response {
    if len(args) != 3 {
        return shim.Error(fmt.Sprintf("Expecting %v arguments {id, status, created_at}, but got %v", 3, len(args)))
    }

    itemID := args[0]
    if len(itemID) == 0 {
        return shim.Error("id field is required")
    }
    status := args[1]
    if len(status) == 0 {
        return shim.Error("status field is required")
    }
    createdAt, err := time.Parse(time.RFC3339, args[2])
    if err != nil {
        return shim.Error("created_at is not a valid datetime string")
    }

    item := itemStruct{
        ID:        itemID,
        CreatedAt: createdAt,
    }

    itemAsJSONBytes, err := json.Marshal(item)
    if err != nil {
        return shim.Error(err.Error())
    }

    return shim.Success(itemAsJSONBytes)
}

func getPendingItems(stub shim.ChaincodeStubInterface, args []string) peer.Response {
    var bookmark string

    if len(args) > 0 && len(args[0]) > 0 {
        bookmark = args[0]
    }

    queryString := `{
        "selector": {
            "status": "pending"
        },
        "sort": [
            {"created_at": "desc"}
        ]
    }`
    result, pagination, err := queryWithPagination(stub, queryString, 20, bookmark)
    if err != nil {
        return shim.Error(err.Error())
    }

    return shim.Success(constructResponse(result, pagination).Bytes())
}

func queryWithPagination(stub shim.ChaincodeStubInterface, queryString string, pageSize int32, bookmark string) (map[string]string, string, error) {
    var pagination string
    iterator, meta, err := stub.GetQueryResultWithPagination(queryString, pageSize, bookmark)
    if err != nil {
        return nil, pagination, err
    }
    defer iterator.Close()

    result, err := iterateResult(iterator)
    if err != nil {
        return nil, pagination, err
    }

    pagination = fmt.Sprintf(`{"count": %v, "next_page_token": "%v"}`, meta.FetchedRecordsCount, meta.Bookmark)
    return result, pagination, nil
}

func constructResponse(items map[string]string, pagination string) *bytes.Buffer {
    // buffer is a JSON array containing QueryResults
    var buffer bytes.Buffer

    if len(pagination) > 0 {
        buffer.WriteString(`{"data":`)
    }

    buffer.WriteString(`[`)

    bArrayMemberAlreadyWritten := false
    for _, val := range items {
        // Add a comma before array members, suppress it for the first array member
        if bArrayMemberAlreadyWritten == true {
            buffer.WriteString(",")
        }
        buffer.WriteString(val)
        bArrayMemberAlreadyWritten = true
    }
    buffer.WriteString("]")

    if len(pagination) > 0 {
        buffer.WriteString(`,"pagination":`)
        buffer.WriteString(pagination)
        buffer.WriteString("}")
    }

    return &buffer
}

func iterateResult(iterator shim.StateQueryIteratorInterface) (map[string]string, error) {
    result := map[string]string{}

    for iterator.HasNext() {
        queryResponse, err := iterator.Next()
        if err != nil {
            return nil, err
        }
        result[queryResponse.Key] = string(queryResponse.Value)
    }

    return result, nil
}

// SmartContract : Smart contract struct
type SmartContract struct {
}

// Init : This method is called when chaincode is initialized or updated.
func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) peer.Response {
    return shim.Success(nil)
}

// Invoke : This method is called when any transaction or query fired
func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    // Retrieve the requested Smart Contract function and arguments
    function, args := stub.GetFunctionAndParameters()

    // Route to the appropriate handler function to interact with the ledger appropriately
    // Transactions
    if function == "createItem" {
        return createItem(stub, args)
    }

    // Queries
    if function == "getItems" {
        return getItems(stub, args)
    }

    return shim.Error("Invalid function")
}

func main() {
    // Create a new Smart Contract
    err := shim.Start(new(SmartContract))

    if err != nil {
        fmt.Printf("Error creating new Smart Contract: %s", err)
    }
}

Он создает и актив, который может иметь другой статус в зависимости от того, что было передано,и я определил одну функцию запроса, которая выбирает только pending элементов.

Я применил сортировку, но результат все еще случайный, может ли кто-нибудь помочь мне здесь и указать, где я ошибаюсь в этом?

1 Ответ

1 голос
/ 25 марта 2019

поле сортировки должно присутствовать в селекторе!

что-то вроде:

queryString := `{
    "selector": {
        "created_at": "$gt": null
        "status": "pending"
    },
    "sort": [
        {"created_at": "desc"}
    ]
}`

или (диапазон)

 queryString := `{
    "selector": {
        "created_at":  {
        "$gt": "2015-01-01T00:00:00Z",
        "$lt": "2019-01-01T00:00:00Z"
        },
        "status": "pending"
    },
    "sort": [
        {"created_at": "desc"}
    ]
}`

По документам - доиспользуйте сортировку и убедитесь, что:

  • Как минимум одно из полей сортировки включено в селектор.
  • Уже определен индекс со всеми полями сортировки в том же порядке.
  • Каждый объект в массиве сортировки имеет один ключ.
  • Если объект в массиве сортировки не имеет одного ключа, результирующий порядок сортировки зависит от реализации и может измениться.

Кроме того, как fyi Find не поддерживает несколько полей с разными порядками сортировки, поэтому направления должны быть либо восходящими, либо все нисходящими.

См. Также CouchDBсортировка не работает

...