简体   繁体   中英

Trouble getting response from hyperledger fabric getStateByRange

Im using createCompsiteKey , and getSateByRange only returns {"done":true} . I tried to replace createCompsiteKey with concat key part to make the key as follows. getSateByRange only returns {"done":true} , I'm using "fabric-shim" v1.4.0 and "fabric-contract-api" v1.4.0. "fabric-peer" image is 1.4.6.

Code for addState to db is below:

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));
}

If I use createCompsiteKey , how can getSateByRange find my records? Or what condition fabric key must meet?

any suggestion, Thank you.

In previous versions of Fabric, getStateByRange API used to return composite keys even when doing a range query on simple keys. For example, the following range query on marble02 chaincode example returned both simple keys such as marble2 , marble3 , and composite keys such as color~namebluemarble2 , color~namebluemarble2 where it should have returned only marble2 and marble3 .

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

Query Result:

[
    {"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"}}
]

There was no way for Fabric to differentiate between a simple or composite so that GetStateByRange() could return only simple keys.

Composite keys have an objectType prefix. Each part of composite key is delimited by null character for example chaincodeid 0x00 objectType 0x00 ck1 0x00 ck2 0x00 . This design ensured that various composite key types have an objectType namespace to guarantee no collisions across types. You can check this yourself by hovering over copy icon on any CouchDB record which have a composite key like in the image below. couchdb-composite-key

Now, getStateByRange() returns only simple keys and getStateByPartialCompositeKey() returns only composite keys. The namespaces for simple keys and composite keys are different to avoid collisions. For more information on this, you can refer to this thread , where Fabric maintainers had a discussion on how to approach this issue.

If you do an unbounded range query on start & end, you won't see any composite key in the results. I tried it myself and these were the results that I received.

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

Output:

[
    {"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}
    }
]

However, when I kept \ as my start key, I received records that had composite key as well.

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

Output:

[
    {"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}
    }
]

So, in conclusion, I think you shouldn't use getStateByRange API, but getStateByPartialCompositeKey to fetch records which have composite keys.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM