无法从超级账本结构getStateByRange获取响应

时间:2020-07-29 09:11:05

标签: node.js hyperledger-fabric

我正在使用createCompsiteKey,而getSateByRange仅返回{"done":true}。 我尝试用concat密钥部分替换createCompsiteKey来制作密钥,如下所示。 getSateByRange仅返回{"done":true},我使用的是“ fabric-shim” v1.4.0和“ fabric-contract-api” v1.4.0。 “ fabric-peer”图像为1.4.6。

addState到db的代码如下:

class StateList {
    async addState(state){
    let keyParts = state.getSplitKey();
    let keyPrefix = (String)(keyParts.slice(0,1));
    let keyOthers = keyParts.slice(1);
    
    /*. comment createCompositeKey
    let key = this.ctx.stub.createCompositeKey(keyPrefix, keyOthers);
    */
    let key = keyParts.map(part => part).join('');

    let data = State.serialize(state);
    await this.ctx.stub.putState(key, data);
   }
}

class State {
    constructor(stateClass, keyParts) {
        this.class = stateClass;
        this.key = State.makeKey(keyParts);
    }
    static makeKey(keyParts) {
        return keyParts.map(part => part).join(':');
    }
    static splitKey(key){
        return key.split(':');
    }
}

async getDevCollectByRange(ctx, startKey, endKey){
    let args = [];
    args[0] = startKey;
    args[1] = endKey;
    let xiotdatadevlist = await ctx.xiotDataDevList.getDevByRange(args);
    return Buffer.from(xiotdatadevlist);
}

async getAllResults(iterator){
    let allResults = [];
        while (true) {
        const res = await iterator.next();

        if (res.value && res.value.value.toString()) {
            console.log(res.value.value.toString('utf8'));

            const Key = res.value.key;
            let Record;
            try {
                Record = JSON.parse(res.value.value.toString('utf8'));
            } catch (err) {
                console.log(err);
                Record = res.value.value.toString('utf8');
            }
            allResults.push({ Key, Record });
        }
        if (res.done) {
            await iterator.close();
            return allResults;
        }
    }       
}

async getObjectsByRange(args) {

    if (args.length < 2) {
        throw new Error('Incorrect number of arguments. Expecting 2');
    }
    // date 
    const startKey = args[0];
    const endKey = args[1];
    
    const resultsIterator = await this.ctx.stub.getStateByRange(startKey, endKey);
    let results = await this.getAllResults(resultsIterator, false);

    return Buffer.from(JSON.stringify(results));
}

如果我使用createCompsiteKeygetSateByRange如何找到我的记录? 还是织物密钥必须满足什么条件?

任何建议,谢谢。

1 个答案:

答案 0 :(得分:0)

在Fabric的早期版本中,getStateByRange API用于返回复合键,即使在对简单键进行范围查询时也是如此。例如,以下对marble02链码示例的范围查询返回了应该返回的简单键(例如marble2marble3和组合键(例如color~namebluemarble2color~namebluemarble2)仅marble2marble3

$ peer chaincode query -n mycc1 -v 0 -c {"Args":["getMarblesByRange","a","z"]} -o 127.0.0.1:7050 -C ch1

查询结果:

[
    {"Key":"color~namebluemarble3", "Record":}
    {"Key":"color~nameredmarble2", "Record":},
    {"Key":"marble2", "Record":{"docType":"marble","name":"marble2","color":"red","size":50,"owner":"tom"}},
    {"Key":"marble3", "Record":{"docType":"marble","name":"marble3","color":"blue","size":70,"owner":"tom"}}
]

Fabric无法区分简单键还是复合键,因此GetStateByRange()只能返回简单键。

复合键具有objectType前缀。复合键的每个部分都由空字符定界,例如chaincodeid 0x00 objectType 0x00 ck1 0x00 ck2 0x00。这种设计确保了各种组合键类型都有一个objectType命名空间,以确保不同类型之间不会发生冲突。您可以将鼠标悬停在具有复合键的任何CouchDB记录上的 copy 图标上,如下图所示。 couchdb-composite-key

现在,getStateByRange()仅返回简单键,而getStateByPartialCompositeKey()仅返回复合键。简单键和组合键的名称空间不同,以避免冲突。有关此的更多信息,您可以参考此thread,Fabric维护人员在其中讨论了如何解决此问题。

如果您在开始和结束时执行无范围查询,则结果中将看不到任何复合键。我自己尝试过,这些是我收到的结果。

peer chaincode query -n marbles -C mychannel -c '{"Args":["getMarblesByRange", "", ""]}'

输出:

[
    {"Key":"azurite","Record": 
        {"color":"yellow","docType":"marble","name":"azurite","owner":"john","size":2}
    },
    {"Key":"marble1","Record": 
        {"color":"red","docType":"marble","name":"marble1","owner":"tom","size":50}
    },
    {"Key":"marble2","Record": 
        {"color":"blue","docType":"marble","name":"marble2","owner":"tom","size":70}
    }
]

但是,当我将\u0000用作开始键时,我也收到了包含复合键的记录。

peer chaincode query -n marbles4 -C mychannel -c '{"Args":["getMarblesByRange", "\u0000", ""]}'

输出:

[
    {"Key":"\u0000color~name\u0000blue\u0000marble2\u0000","Record":"\u0000"}, 
    {"Key":"\u0000color~name\u0000red\u0000marble1\u0000","Record":"\u0000"}, 
    {"Key":"\u0000color~name\u0000yellow\u0000azurite\u0000","Record":"\u0000"}, 
    {"Key":"azurite","Record": 
        {"color":"yellow","docType":"marble","name":"basil","owner":"john","size":2}
    },
    {"Key":"marble1","Record": 
        {"color":"red","docType":"marble","name":"marble1","owner":"tom","size":50}
    },
    {"Key":"marble2","Record": 
        {"color":"blue","docType":"marble","name":"marble2","owner":"tom","size":70}
    }
]

因此,总而言之,我认为您不应该使用getStateByRange API,而应该使用getStateByPartialCompositeKey来获取包含复合键的记录。