简体   繁体   中英

Is there a good way to index a lot of data in a smart contract to be able to read it efficiently?

I am writing a solidity smart contract in which users would be able add a string (eg. one line joke), and other users should be able to vote on these jokes. If there are for example a million jokes in the contract (all with a different vote count), Would it be possible to rank these jokes by vote count? Eg. display the highest voted 10 of the million jokes? I know it is possible on a small scale, but on a larger scale I'm not so sure.

A variant of the contract that implements the main functionality you need is attached below:

  • registration of "jokes" records
  • registration of voting without repeats
  • definition of the top 10 (I hope I was not mistaken in the sorting algorithm).

The hash from its text is used as the identifier of the "joke".

However, in order to provide users with quality functionality, you need an external application that will monitor the events JokeCreated and JokeVoted of this contract and maintain an external database of "jokes" records. This is because Ethereum contracts are ineffective for iterative operations with large arrays and you need an external service to:

  • providing users with a common list of "jokes"
  • providing users with a general rating list of "jokes" When using an external application, you can also exclude the function of determining the top 10 from the contract (in function VotesForJoke ), which will significantly reduce the cost of the voting transaction. In addition, you need to keep in mind the problem of identifying users to avoid re-voting, since in general it cannot be solved at the level of Ethereum itself.
pragma solidity ^0.5.8;

contract Jokes
{

    struct Joke 
    {
         string                 text ;
        address                 sender ;
        bytes32                 author ;
        uint256                 votes ;
        mapping (bytes32=>bool) voters ;
    }

    mapping (bytes32 => Joke)  JokesList ;
                  bytes32[10]  Top10 ;

    event JokeCreated(bytes32 hash, string text, address sender, bytes32  author) ; 
    event JokeVoted  (bytes32 hash, bytes32 voter) ; 

    constructor() public
    {
    }

   function NewJoke(string  memory text_, bytes32  author_) public 
   {
       bytes32  hash ;
    
            hash=keccak256(abi.encodePacked(text_)) ;

       if(JokesList[hash].author!=0x00)  require(false) ;

         JokesList[hash] =Joke({   text: text_, 
                                 sender: tx.origin,
                                 author: author_,
                                  votes: 0         }) ;

      emit JokeCreated(hash, text_, tx.origin, author_) ; 
   }


   function VotesForJoke(bytes32  hash_, bytes32  voter_) public 
   {
      uint256  votes ;
      uint256  i ;

// Check for existance
       if(JokesList[hash_].author==0x00)  require(false) ;
// Check for re-voting
       if(JokesList[hash_].voters[voter_]==true)  require(false) ;

          JokesList[hash_].voters[voter_]=true ;
          JokesList[hash_].votes++ ;

// Ordering top 10
            votes=JokesList[hash_].votes ;

        for(i=9 ; i>=0 ; i--)
          if(votes>=JokesList[Top10[i]].votes)
          {
              if(i!=9 && Top10[i]!=hash_)  Top10[i+1]=Top10[i] ;
          }
          else
          {
               break ;  
          }

          if(i!=9)  Top10[i+1]=hash_ ;

// Emit event of voting
      emit JokeVoted(hash_, voter_) ; 
   }

   function GetJoke(bytes32  hash_) public view returns (string memory, address, bytes32,uint256 retVal)
   {
        return(JokesList[hash_].text, JokesList[hash_].sender, JokesList[hash_].author, JokesList[hash_].votes) ;
   }

   function GetTop10() public view returns (bytes32[10] memory retVal)
   {
       return(Top10) ;
   }
    
}

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