无法从超级账本结构getStateByRange和getStateByPartialCompositeKey获得响应

时间:2019-09-05 13:10:40

标签: node.js hyperledger-fabric

我很难从这种方法中得到答案,没有办法,我只能在迭代器中获得最终完成的对象,而没有其他对象。我肯定知道区块链中有对象,可以使用getState方法获取它们。

这是我的getStateByPartialCompositeKey代码:

public async getStatesByPartialKey(className: string, key: string): Promise<any> {
    const states = [];
    const datas = [];
    const iterator = await this.ctx.stub.getStateByPartialCompositeKey(className, [key]);

    while (true) {
        const data = await iterator.next();
        datas.push(data);

        if (data.value && data.value.value.toString()) {
            const state = State.deserialize(data.value.value, this.supportedClasses);
            states.push(state);
        }
        if (data.done) {
            await iterator.close();
            return datas;
        }
    }
}

这是我的getStateByRange方法代码:

public async getStatesByRange(startKey: string, endKey: string): Promise<any> {
    const states = [];
    const datas = [];
    const iterator = await this.ctx.stub.getStateByRange(startKey, endKey);

    while (true) {
        const data = await iterator.next();
        datas.push(data);

        if (data.value && data.value.value.toString()) {
            const state = State.deserialize(data.value.value, this.supportedClasses);
            states.push(state);
        }
        if (data.done) {
            await iterator.close();
            return datas;
        }
    }
}

这是我在区块链中拥有的对象之一:

{
    "class":"com.example.state",
    "key":"\"COMPANY1\":\"1f5ee25d-546e-46d2-96cd-f7b7a347f84f\"",
    "currentState":1,
    "id":"1f5ee25d-546e-46d2-96cd-f7b7a347f84f",
    "issuer":"COMPANY1"
}

这是我使用它们的方式:

getStatesByPartialKey('com.example.state', 'COMPANY1');
getStatesByRange('COMPANY0', 'COMPANYz');

这是我得到的唯一答案:

[{"done":true}]

我在做什么错?我正在使用“ fabric-shim”:“ ^ 1.2.0”。

谢谢

3 个答案:

答案 0 :(得分:1)

尝试下面的代码段

let startKey = 'COMPANY0';
let endKey = 'COMPANYz';

// empty string for start and end keys returns full state
let iterator = await stub.getStateByRange(startKey, endKey);

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

  if (res.value && res.value.value.toString()) {
    let jsonRes = {};
    console.log(res.value.value.toString('utf8'));

    jsonRes.Key = res.value.key;
    try {
      jsonRes.Record = JSON.parse(res.value.value.toString('utf8'));
    } catch (err) {
      console.log(err);
      jsonRes.Record = res.value.value.toString('utf8');
    }

    allResults.push(jsonRes);
  }
  if (res.done) {
    console.log('end of data');
    await iterator.close();
    console.info(allResults);
    return Buffer.from(JSON.stringify(allResults));
  }

答案 1 :(得分:1)

我遇到的问题是创建密钥,我使用的是stub.createCompositeKey,但是它在密钥的开头创建了带有u0000字符的密钥,而stub.getStateByRange方法找不到任何东西,即使我寻找使用stub.createCompositeKey方法读取的范围。

我不得不改变创建密钥的方式,然后我开始查找记录。

谢谢

答案 2 :(得分: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