Skip to content

Instantly share code, notes, and snippets.

@dpkirchner
Created June 3, 2020 22:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dpkirchner/f2448fef0d8b777a2413f415c4333036 to your computer and use it in GitHub Desktop.
Save dpkirchner/f2448fef0d8b777a2413f415c4333036 to your computer and use it in GitHub Desktop.
dgraph, using groupby to report votes
node recreate.js
node vote.js -p 'What do?' -c 'Candidate A' -v 'Voter B'
node vote.js -p 'What do?' -c 'Candidate A' -v 'Voter D'
node vote.js -p 'What do?' -c 'Candidate C' -v 'Voter D'
node vote.js -p 'What do?' -c 'Candidate C' -v 'Voter E'
node vote.js -p 'What do?' -c 'Candidate C' -v 'Voter A'
node votes.js -p 'What do?'
# output:
# Candidate A: 1
# Candidate C: 3
node vote.js -p 'What do?' -c 'Candidate B' -v 'Voter C'
node votes.js -p 'What do?'
# output:
# Candidate A: 1
# Candidate B: 1
# Candidate C: 3
node vote.js -p 'What do?' -c 'Candidate A' -v 'Voter C'
node votes.js -p 'What do?'
# output:
# Candidate A: 2
# Candidate C: 3
{
"name": "votedemo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"commander": "^5.1.0",
"dgraph-js": "^20.3.0"
},
"author": "",
"license": "ISC"
}
// (Re)creates the voting schema, wipes the data, and inserts hardcoded values
//
// node recreate.js
const dgraph = require('dgraph-js');
const grpc = require('grpc');
const schemas = `
type Candidate {
candidate_name
}
candidate_name: string @index(exact) .
type Voter {
voter_name
}
voter_name: string @index(exact) .
type Vote {
vote_voter
vote_candidate
}
vote_voter: uid @reverse .
vote_candidate: uid @reverse .
type Poll {
poll_title
poll_votes
}
poll_title: string @index(exact) .
poll_votes: [uid] @count @reverse .
`;
const alter = async client => {
const op = new dgraph.Operation();
op.setSchema(schemas);
await client.alter(op);
};
const deleteAll = async client => {
const txn = client.newTxn();
try {
const mu = new dgraph.Mutation();
mu.setDelNquads(`
uid(candidate) * * .
uid(voter) * * .
uid(vote) * * .
uid(poll) * * .
`);
const req = new dgraph.Request();
req.setCommitNow(true);
req.addMutations(mu);
req.setQuery(`
query {
candidate as var(func: type(Candidate))
voter as var(func: type(Voter))
vote as var(func: type(Vote))
poll as var(func: type(Poll))
}
`);
await txn.doRequest(req);
} finally {
txn.discard();
}
};
const createPoll = async client => {
const txn = client.newTxn();
try {
const mu = new dgraph.Mutation();
mu.setSetJson([{
'dgraph.type': 'Poll',
poll_title: 'What do?',
uid: '_:poll',
}, ...['Voter A', 'Voter B', 'Voter C', 'Voter D', 'Voter E'].map(name => ({
'dgraph.type': 'Voter',
voter_name: name,
})), ...['Candidate A', 'Candidate B', 'Candidate C'].map(name => ({
'dgraph.type': 'Candidate',
candidate_name: name,
}))]);
const req = new dgraph.Request();
req.setCommitNow(true);
req.addMutations(mu);
await txn.doRequest(req);
} finally {
txn.discard();
}
};
const main = async () => {
const stub = new dgraph.DgraphClientStub(
'127.0.0.1:9080',
grpc.credentials.createInsecure()
);
const client = new dgraph.DgraphClient(stub);
await alter(client);
await deleteAll(client);
await createPoll(client);
};
main();
// Cast vote
//
// node vote.js -p 'What do?' -c 'Candidate C' -v 'Voter E'
const program = require('commander');
const dgraph = require('dgraph-js');
const grpc = require('grpc');
const insertMutation = () => {
const mu = new dgraph.Mutation();
mu.setSetJson([{
'dgraph.type': 'Vote',
vote_voter: {uid: 'uid(voter)'},
vote_candidate: {uid: 'uid(candidate)'},
uid: '_:blank-0',
}, {
poll_votes: {uid: '_:blank-0'},
uid: 'uid(poll)',
}]);
mu.setCond('@if(eq(len(voter), 1) and eq(len(candidate), 1) and eq(len(poll), 1) and eq(len(vote), 0))');
return mu;
};
const updateMutation = () => {
const mu = new dgraph.Mutation();
mu.setSetJson({
vote_voter: {uid: 'uid(voter)'},
vote_candidate: {uid: 'uid(candidate)'},
uid: 'uid(vote)',
});
mu.setCond('@if(eq(len(voter), 1) and eq(len(candidate), 1) and eq(len(poll), 1) and eq(len(vote), 1))');
return mu;
};
const vote = async (client, params) => {
const {pollTitle, voterName, candidateName} = params;
const txn = client.newTxn();
try {
const muInsert = insertMutation();
const muUpdate = updateMutation();
const req = new dgraph.Request();
req.setCommitNow(true);
req.addMutations(muInsert);
req.addMutations(muUpdate);
req.setQuery(`
query query($voterName: string, $candidateName: string, $pollTitle: string) {
voter as var(func: eq(voter_name, $voterName)) @filter(type(Voter))
candidate as var(func: eq(candidate_name, $candidateName)) @filter(type(Candidate))
poll as var(func: eq(poll_title, $pollTitle)) @filter(type(Poll)) {
vote as poll_votes @cascade {
uid
vote_voter @filter(eq(voter_name, $voterName))
}
}
}
`);
const varsMap = req.getVarsMap();
varsMap.set('$voterName', voterName);
varsMap.set('$candidateName', candidateName);
varsMap.set('$pollTitle', pollTitle);
await txn.doRequest(req);
} finally {
txn.discard();
}
};
program.
requiredOption('-p, --poll <string>', 'Poll title').
requiredOption('-c, --candidate <string>', 'Candidate name').
requiredOption('-v, --voter <string>', 'Voter name');
program.parse(process.argv);
const main = async (pollTitle, voterName, candidateName) => {
const stub = new dgraph.DgraphClientStub(
'127.0.0.1:9080',
grpc.credentials.createInsecure()
);
const client = new dgraph.DgraphClient(stub);
await vote(client, {pollTitle, voterName, candidateName});
};
main(program.poll, program.voter, program.candidate);
// Report vote count
//
// node votes.js -p 'What do?'
const program = require('commander');
const dgraph = require('dgraph-js');
const grpc = require('grpc');
const votes = async (client, pollTitle) => {
const txn = client.newTxn();
try {
const query = `
query query($pollTitle: string) {
result(func: eq(poll_title, $pollTitle)) @filter(type(Poll)) {
uid
poll_votes @groupby(vote_candidate) {
c: count(uid)
}
}
candidates(func: type(Candidate)) {
uid
candidate_name
}
}
`;
const queryResult = await txn.queryWithVars(
query,
{'$pollTitle': pollTitle}
);
const {
result,
candidates: candidatesIn,
} = queryResult.getJson();
const candidates = {};
candidatesIn.forEach(c => candidates[c.uid] = c.candidate_name);
result[0].poll_votes[0]['@groupby'].forEach(x => {
console.log(candidates[x.vote_candidate] + ': ' + x.c);
});
} finally {
txn.discard();
}
};
program.
requiredOption('-p, --poll <string>', 'Poll title');
program.parse(process.argv);
const main = async pollTitle => {
const stub = new dgraph.DgraphClientStub(
'127.0.0.1:9080',
grpc.credentials.createInsecure()
);
const client = new dgraph.DgraphClient(stub);
await votes(client, pollTitle);
};
main(program.poll);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment