You want "a user ID, a list of voters, and the outcome". Let's see how that looks as a tuple:
{User :: user_id(), [Voters :: user_id()], Outcome :: boolean()}
Not so hard. A list of those tuples -- also not hard. A dict of those is a bit more complicated, because you wind up with (essentially, if this were a proplist, using the types above):
{User, {[Voters], Outcome}}
Which is a bit less happy to deal with. You may want to filter by outcome, for example, but that is now now buried within a tuple within a tuple whereas a list of flat tuples permits simple filtering (either a real filter, or just guarding a list comprehension, or whatever) or use lists:keysearch/3
. This makes complex searches more awkward, especially if you want to know how many times a particular voter has voted to kick someone.
The basic problem could certainly be made easier by using ETS, as it has facilities for dealing fully with tuples in a much quicker way than lists of tuples using keysearch/3
(and, I am assuming you have thousands and thousands of cases so that lists of tuples is inadequate -- but as always, try it out that way first, you might find that lists of tuples is totally adequate!). On the other hand, if the search cases get even a little more complex, or the cases need to be stored durably and still benefit from in-memory manipulation, or you need multiple indexes, etc. then you should really move on to Mnesia.
Beyond that... you are dealing with nested data, and while that is actually just fine 90% of the time, that other 10% of the time you wind up either reinventing relational data (but worse, with less actual utility, and slower) or just suffering through a bunch of baroque procedural code to achieve an effect that could be had for free with very little pain by simply using something like Postgres (I happen to be extremely familiar with this DB, so to me its a "lightweight solution" -- I understand this is not the case for everyone).
For reference, your data, when decomposed looks like this (assuming that user ids are email addresses for the sake of the example):
table user
attributes
id EmailAddress
conditions
pk id
table kick
attributes
id UUID
user EmailAddress
outcome Boolean
conditions
pk id
fk user
table vote
attributes
kick UUID
user EmailAddress
conditions
pk (kick user)
fk kick
fk user
While it is obvious that the User
and [Voter]
components of the tuples described above reference user records, it is not quite as obvious why trying to pull a list of all votes cast by a certain user using tuples is such a nasty process. When we look at the decomposed data we realize that this is three tables, and we really wish we could run a query on the vote
one by itself if you have this requirement. But if you don't have that requirement, then don't worry about it and just use tuples in ETS or Mnesia! :-) This kind of data is pretty tiny in Erlang.