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