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.
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.