EOSIO / eosjs

General purpose library for the EOSIO blockchain.
http://eosio.github.io/eosjs
MIT License
1.43k stars 463 forks source link

how eosjs get table record by primary key?? #138

Closed healthwallet closed 6 years ago

healthwallet commented 6 years ago
    var code='liontable';
    var table='accounteos';
    (this.$gobal.eos.getTableRows(true,code,'liontable',table).then(function (value) {
      console.log(value);
      for( var j = 0; j < value.rows.length; j++) {
          if(value.rows[j].ID == 10)
          {
            console.log(value.rows[j]);
          }
      }

if i write like this ,it can't get data,the primary key of my table is ID(uint_t) (this.$gobal.eos.getTableRows(true,code,10,table).then(function (value)

jcalfee commented 6 years ago

Looks like you need a table_key after table:

// json, code, scope, table, table_key
eos.getTableRows(true, code, 'liontable', table, tableKey)
healthwallet commented 6 years ago

I add the table_key para,but i get all of the table data ,not the primary key data ,why ?? thany you.

    (this.$gobal.eos.getTableRows(true,code,'liontable',table,10).then(function (value) {
      console.log(value);
      // for( var j = 0; j < value.rows.length; j++) {
      //     if(value.rows[j].ID == 10)
      //     {
      //       console.log(value.rows[j]);
      //     }
      // }

      return value; })) ;

return data as follow

{rows: Array(2), more: false}more: falserows: Array(2)0: {ID: 1, loginID: "ac1", loginName: "ac2", eosAcc: "ac3", memberType: 4, …}1: {ID: 10, loginID: "ac1", loginName: "ac2", eosAcc: "ac3", memberType: 4, …}length: 2proto: Array(0)proto: Object

jcalfee commented 6 years ago

Yes, this could be a bug .. A core dev will try to look at it today.

jcalfee commented 6 years ago

possibly related: https://github.com/EOSIO/eosjs/issues/147

jcalfee commented 6 years ago

I got some feedback: "Well seeing how table_key is not used in our software anywhere it can be whatever you want ;)" .. he says 147 may be the same thing..

I'm thinking it must your implementation in your smart contract.

angelol commented 6 years ago

So that answer means it's not currently possible to fetch a database record by ID?

Is there a plan to add this functionality?

Will it also be possible to find by secondary indexes?

chris-allnutt commented 6 years ago

@angelol the table in a contract is not a traditional database, you can't query it as such either. If you have a need to index and search the data I would recommend cacheing the data to a datastore on your end in a traditional db or document db

angelol commented 6 years ago

@chris-allnutt Well, it is advertised as a fully featured database. I quote from the documentation wiki:

The EOSIO Multi-Index API a is patterned after Boost Multi-Index Containers. This API provides a model for object storage with rich retrieval capabilities, enabling the use of multiple indices with different sorting and access semantics.

So clearly, the functionality is there and can be accessed from within a smart contract. Is there a reason as to why not to expose that functionality via eosjs?

angelol commented 6 years ago

I just realized, fetching a database record by ID works when using lower_bound and upper_bound. The table_key parameter seems to get ignored though.

This works: eos.getTableRows({json:true, scope: account, code: contract, table: table, limit:1, lower_bound: id, upper_bound: id+1}).then(res => { let row = res.rows[0]; });

chris-allnutt commented 6 years ago

I believe that is for use in contracts "The EOSIO Multi-Index API provides a C++ interface to the EOSIO database" . I don't know what would be involved to expose that via RPC but you could ask for it in the eos repository.

cipherzzz commented 6 years ago

I agree, this is kindof a pain - I had to end up doing this:

getGrades(school_id) {
        this.props.eos.getTableRows({
          "json": true,
          "scope": 'admin',
          "code": 'lottery.code',
          "table": "grade",
          "table_key": 'school_key',
          "lower_bound": school_id,
        }).then(result => {
          const filteredRows = result.rows.filter((grade)=> grade.schoolfk == school_id)  
          console.log(JSON.stringify(filteredRows))
          this.setState({grades: filteredRows})
        }).catch((error) =>{
          this.setState(error)
        })
      }
MessyComposer commented 6 years ago

@cipherzzz I like your approach, how ever when you have a lot of entries, it becomes cumbersome as you have to query multiple times. Depending on use case it may be fine.

I got around this by making a action in my smart contract that can be used to get data from tables. ( I know it uses bandwidth and processing time, but that's the best alternative I have for now)

cipherzzz commented 6 years ago

@MessyComposer - How do you return data from the smart contract action? I didn't know you could return data from an action and had to query tables via the methods above?

jcalfee commented 6 years ago

Release eosjs@16.0.0 adds two parameters to get_table_rows .. key_type and index_position ..

ajose01 commented 6 years ago

@jcalfee I'm still learning how to form the requests. any documentation on how to use key_type / index_position? 🙏

jcalfee commented 6 years ago

I just recently added this: https://github.com/EOSIO/eosjs-api/blob/master/docs/api.md#eos.getTableRows

The docs are copied from the c++ code..

Aniket-Engg commented 6 years ago

Release eosjs@16.0.0 adds two parameters to get_table_rows .. key_type and index_position ..

@jcalfee what functionality these two add? I mean how they are helping in getting rows?

samkirton commented 6 years ago

Anyone still struggling with getting rows by or pagination by i64 primary key, please see the answer at #154