0

I'm developing an android voting application. I have this code that inserts voters emails into a candidates key to help me count the total votes.

public static void insertvote(String userkey, String categ, String candId, String uid) {
            DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
            DatabaseReference totalVotesRef = rootRef.child("votes").child(categ).child(candId);
            Vote vote = new Vote(userkey);
            totalVotesRef.child(uid).setValue(vote.getVoterEmail());

It generates below results in firebase:

Firebase database

How can I enforce an email to only vote once and if it exists in the specific category, it disallows voting again? (For example in the image above, hr@gmail.com has been listed twice instead on only once meaning they can vote for a president twice) Thanks in advance.

  • I already showed you how to structure the data to allow only a single vote in my answer to your previous question: https://stackoverflow.com/questions/60874553/firebase-rule-to-only-allow-one-update-in-android-studio/60879145#60879145. Any reason why you didn't adopt the data structure I showed there? – Frank van Puffelen Mar 28 '20 at 15:03
  • Ngugi k , @FrankvanPuffelen is an expert , you should have taken seriously whatever he suggested you , and you should give preference his answer at that post over my answer at this post – Abhinav Chauhan Mar 28 '20 at 15:13
  • Frank I did try to adopt the answer sir, but as I said I have not worked with Cloud Functions and therefore found myself more stuck. I did not want to bother you a lot out of courtesy. – Ngugi Kariuki Mar 28 '20 at 15:26
  • 1
    Using the data model does not require using Cloud Functions, yet in this question you seem to not have made any of the changes to your data model that I proposed. Your current data model is just not great for the use-case you're trying to implement. If those changes were not clear, comment on my answer to your original question so that I can try to clarify. – Frank van Puffelen Mar 28 '20 at 15:33

2 Answers2

0

I am NOT A FIREBASE EXPERT but i think that query will download all the data for all the votes.

IF I AM NOT WRONG querying all the votes which may be millions and then matching email and category might be an overkill. I think you can create a flat structure for categories and put each category under it and when a voter votes put his id under that category.

like   cartegories :|
                |
                | president|
                |          |id:jrlkjew34234tlk 
                |          |id:rwjelk343243tjlke 
                |          |id:rjlwekr343ljlerer
                |          |
                | prime minister|
                |               |id:iorlue4324uoirew
                |               |id:eri34o3ljlewo234

Now when every time a votes put his id under the category he is trying to vote for and the query just that category and just match the id.

Something like that

public void vote(Voter voter){
    mDatabase.child("categories").child(voter.getCategory()) //getCategory() returns 
    //string that you will put under categories node, like pm , president etc
    .addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot snapShot : dataSnapshot.getChildren()){
                if(snapShot.getValue(String.class).equals(voter.getVoterId))
                   // if you get here he can't vote otherwise he can
          }   
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });

That way you will be querying the particular category of votes , hence fast response and less download and less bill, and you can skip the category field from vote because you will be able to count vote by the new structure

SOMEBODY PLEASE CORRECT ME IF I AM WRONG

And OP can you please tell me what is the reason for saving the single category for a memeber if the member can vote for more than one category

Abhinav Chauhan
  • 1,304
  • 1
  • 7
  • 24
  • Thanks id advance. Let me put this to test and give you feedback – Ngugi Kariuki Mar 28 '20 at 14:45
  • you're welcome , and it may not be the best solution , you can wait for answers of experts in the field if you want, i answered what i thought is a good idea , surely it will work better than what you were doing , but better solution may exist . – Abhinav Chauhan Mar 28 '20 at 15:01
  • Quick question, the "Voter voter" inside the parameters, what is it supposed to represent. Is it like an object? – Ngugi Kariuki Mar 28 '20 at 15:04
  • a voter is an object in real life , it will have fields like age which should be over 18, gender in case you want to know the voting percent male vs female , an address in case you want to know which city has more voting percent , etc, you should create a voter popo it will be more object oriented – Abhinav Chauhan Mar 28 '20 at 15:07
  • What should I pass as the parameter when I call the vote() function? Because Im calling it inside a recyclerview adapter in a onBindViewHolder() method. – Ngugi Kariuki Mar 28 '20 at 15:56
  • i think you have a design problem in the core of app , a voter may not vote everytime recyclerview is drawn on screen ,but if you calling it in the onBindViewHolder you still has access to the adapter data , you can pull a member from it. A suggest rethink your app. – Abhinav Chauhan Mar 28 '20 at 16:04
  • in that case you should paste snapshots of your in app navigation – Abhinav Chauhan Mar 28 '20 at 16:05
  • 1
    @NgugiKariuki i think first the users should get a list of elections which are going on , means the categories , like pm , president , then they should be provided with the names of candidates standing in that election, when user clicks the name , the details of candidate should appear with the promise that candidate make and his vision statement etc , so that the user can vote smartly , on the same page the vote button should be there,, in case you're very new start from building very simple apps, then climb your way up , you will learn a lot in the process – Abhinav Chauhan Mar 28 '20 at 17:13
  • But thats the logic. Its only that I couldnt put all screenshots. This is the logic: login-> vote button ->Categories->candidates available (in the attached recyclerview image). – Ngugi Kariuki Mar 28 '20 at 17:24
0

A simple solution, under each voter profile, add a boolean field: .

If one has done voting, just mark it as True.

Use an if else to check for it by getting the value of hasVoted under the voter.

If the user is allowed to vote for different events, you can make the boolean using the event id, assuming you have developed a well-structured program, where everything has an id. For example, Brexit UK has an id of 123456789, the field will be named as hasVoted123456789. Always query the field when user enters the page.

P/s: Frank presented a cleaner approach using in his previous post.

Angus
  • 3,680
  • 1
  • 12
  • 27
  • 1
    he wants user to vote more than once, like once for president , once for senator , or some other election , if a voter can vote only once the design would be much simple – Abhinav Chauhan Mar 28 '20 at 16:07