I'm using Google App Engine and Objectify 3.1 and slowly learning about denormalization and designing entities based on their usage, but I'm still struggling with some aspects.
I'm currently building a system in which a User entity can participate in a Game entity and need to be able to find all games a user participates in. The way I see it, there's two basic solutions:
Solution 1)
Store a list of user keys (participantKeys) on the game and find the games a member participates in like this:
List<Key<User>> userList = new ArrayList<Key<User>>();
userList.add(new Key<User>(User.class, myUserId));
Collection<Game> games = ofy().query(Game.class).filter("participantKeys in" , userList).list();
Solution 2)
In addition to storing a participant list on the game entity, also store a list of games the user has participated in on the user entity and find the games like this:
User myUser = userDao.getUser(myUserId);
Collection<Game> games = user.getParticipatedGameKeys();
Solution 1 would become pretty slow once there's a lot of games in the system.
Solution 2 would make finding the games faster, but I'll need to constantly keep the list updated as users join and leave games.
The list of games would also become large once a user has been using the system for a long time. I only want to return all games the user is currently participating in, so that would require traversing the list and excluding "historical" games.
Am I missing a more elegant solution? Neither of the above seem very attractive.
Any and all help is greatly appreciated!
Edit:
I decided to try something like Mikl suggested after thinking about alternatives for a long time.. so it's good to hear a solution that's very pretty much exactly like it :-)
I have created a GameParticipation entity which contains a link to the game, a link to the user and all other information that I need to be able to get.
Every time a game is joined, I update the GameParticipation entity to reflect the current state of the game. When a game is left, I delete the entity. Also, when a game is changed, I update all related GameParticipation entities.
I've done a little performance testing and it seems to work reasonably well!