cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Designing a database

Hi everyone 👋

I'm Alain and new here. I started to learn Neo4j and this database is really awesome. I think it would fit for the project I'm starting to work on. The project consists in creating a deckbuilder for a new TCG (trading card game) and I need help to design the schema of the Neo4j database.

Here is the basic functionality :
A player can create some decks that will contain some cards. A card can appear several times in a deck. Each card has a cost and the user can override this cost and chose the number he wants (because some cards has effect that modify the cost of other cards).

I wanted to design the database like this :

  • Nodes for decks
  • Nodes for cards
  • Relationship between decks and cards

My questions are :

  • What is the best way to represent the relationship ? (where cost is optional and represent the cost chosen by the user)
    1. (Card)-[IN {cost?: X}]->(Deck) 
    2. (Deck)-[INCLUDES {cost?: X}]->(Card)
  • How to handle the case when a card is represented several times in a deck ? Because it seems that a relation can't exist multiple times between two nodes (except if the relations has different property values) 
  • How to create and update the deck ? The user can perform multiple actions (adding and removing cards) and then save the modifications. How to perform the difference between the existing data in the database and the new version of the deck ?
  • Maybe I am totally wrong and I need to think about another design (which one ?)

I want to use Neo4j because it seems to be a good choice especially to get statistics when future features will be implemented (particularly when we will want to get the performances of cards and decks in tournaments).

It was a long message, thank you for those who will read this and help me 😊

Have a nice day everyone.

Alain

 

 

 

1 ACCEPTED SOLUTION

Hello @PastaBolo 🙂 (my answer was not sent, sorry for the delay)

  1. Your model looks very good.
  2. No need for two-way relationship, so like that you can even know who sent the invitation, so no two-way.
  3. No you can keep the same type of relationship.
  4. My only doubt is that the relationship between the Deck node and the Tournament node should be removed. Instead it would be better to create a new type of node such as Session which will be linked to the Tournament node and the User node and the Deck node will be connected to this new Session node. Example: (User)-[REGISTERS]->(Session), (Session)-[USED]->(Deck), (Session)-[PARTICIPATES]->(Tournament)

Regards,

Cobra

View solution in original post

16 REPLIES 16

Hello @PastaBolo 😊

  1. I would choose the second option: (Deck)-[INCLUDES {cost: X}]->(Card)
  2. You can create multiple relationships between the same two nodes, you will need to use the CREATE clause and not MERGE clause when you want to add a relationship between the Deck and the Card.
  3. You can add a property in the relationships like status which can have two values: current for the current card in the deck and new for the new card then you can do whatever you want.
  4. The design is very good depending on what you want. Moreover, it is possible to refactor the graph with a few queries so no worries.

Regards,

Cobra

Thank you very much @Cobra for your quick answer, I rellay appreciate that 🙂

  1. Why do you chose this relationship ? Is it a personal preference or the direction can leads to performance issues ?
  2. Oh yeah, thanks ! I used MERGE so much so I forgot CREATE 🙄
  3. I'm not sure this property is necessary. What I wanted to say is that a deck is already created and exists in database. The player want to make some changes for this deck, I don't really know how to apply these changes. Should the user send the new list of cards in the deck and the backend checks for the differences and make a lot of queries to add and remove relationships or maybe we should update the database for each action from the user (adding or removing a card).
  4. Yes, in the tutorial, it seems really easy to refactor a graph. I was wondering if this is still the case in a real world app

Regards,

Alain

No problem 🙂

  1. There is no performance issue, it's just that you used a verb to describe the relationship type, which is good practice.
  2. Even me! 😅
  3. I guess the right answer will depend on several things:
    1. The number of users that will use your application at the same time
    2. The power of the machine that will host your application
    3. Do you want the user to modify what he wants and then save the final result or save on each modification?
    4. So all you have to do is answer the question: How should users interact with my app? The answer will help you choose how to handle things behind.
  4. To be honest, I've never had the case but for sure it will be more difficult and long but not impossible. That's why, you should start with a prototype and after you will scale up when you are sure of the model

Regards,

Cobra

The community is not really that big at the moment. So, performances would not be a problem.
I think I will use Docker and Kubernetes for deployment. I see that there is a Docker image for Neo4j. 
How should users interact with the app, that's the question. I think that both systems described can be suitable for the feature. so I need to compare how difficult the implementations of these two systems are. And I have no idea for the case the deck is updated when the user decide to save the modifications.

 

Regards,

Alain

I see 🙂

Each card will be represented by a relationship, so you will know which one to update, to create or to delete based on the id of the relationship.

Regards,

Cobra

The easiest way would be to update the database for each action.
With the other solution, if we update only when the user clicks the "save" button, we will perform multiple updates at once. I don't really know how to manage it in the best way.

I think that the second solution is the best but hard to set up (or I don't see how it could be easy)

Regards,

Alain

  1. The easiest solution is that your app send the whole deck, so your function will delete the old deck and load the new one.
  2. The second one is to track all changes and to have a query that according the type of change will update, delete or add a card. You can easily do that with Cypher so don't worries and we are here on the forum to help you if needed with queries 🙂

  1. The first solution is brutal but really easy but what about performances ? A deck contains ~60 cards so each time the user click "save", we have to remove ~60 relations and create ~60 relations.

  2. Yeah I thought about that kind of solution. The user sends a list of actions and payload for each action.

Thank you, I will need some help for sure 😅

I will think about other features and come back with a diagram of the database. Could you comment when I post it ? That would help me a lot !

Regards,

Alain

  1. Yeah, I said easier but not more efficient 🙂
  2. It's the best solution a far as I see.

No problem, happy to help 😅

I will try my best 🙂

Regards,

Cobra

Hello 😁

Here is the first schema of the database :db graph.png

  • A card has a type (deity, angel, miracle...)
  • A card belongs to zero, one or multiple kingdoms
  • There are new extensions periodically with new cards
  • A deck includes cards
  • A deck is built by a user
  • A use takes part in a tournament with a deck => ideally, I think the deck should be locked when this is the case => maybe I should add a label "Locked" for the deck or check if the deck has a PARTICIPATES relationship
  • Users can have friends
  • Users can be part of groups
  • A deck can be private, public, shared with certain users, shared with friends or shared with a group

  1. What are your first impressions impressions about this graph ?
  2. Should the IS_FRIEND relationship be bidirectional ? (be represented by 2 relationships in both way). I know that we don't really care about the direction and it has no issue but how this kind of relationship is usually represented ?
  3. Decks have SHARED_WITH relationship with two different types of node (User and Group). Is that a problem or should it be more specific with two different types of  relationship ?

I hope everything is clear 🙂

Regards,

Alain

Hello @PastaBolo ‌‌

  1. Your model looks very good.
  2. No need for two-way relationship, so like that you can even know who sent the invitation, so no two-way.
  3. No you can keep the same type of relationship.
  4. My only doubt is that the relationship between the Deck node and the Tournament node should be removed. Instead it would be better to create a new type of node such as Session which will be linked to the Tournament node and the User node and the Deck node will be connected to this new Session node. Example: (User)-[REGISTERS]->(Session), (Session)-[USED]->(Deck), (Session)-[PARTICIPATES]->(Tournament)
  5. You can even replace the Tournament by a new node called Edition if you want to have several editions for a tournament. Example: (Session)-[PARTICIPATES]->(Edition), (Tournament)-[HAS]->(Edition) (I'm sure you can find a better verb than HAS)

Regards,

Cobra

Hello @PastaBolo 🙂 (my answer was not sent, sorry for the delay)

  1. Your model looks very good.
  2. No need for two-way relationship, so like that you can even know who sent the invitation, so no two-way.
  3. No you can keep the same type of relationship.
  4. My only doubt is that the relationship between the Deck node and the Tournament node should be removed. Instead it would be better to create a new type of node such as Session which will be linked to the Tournament node and the User node and the Deck node will be connected to this new Session node. Example: (User)-[REGISTERS]->(Session), (Session)-[USED]->(Deck), (Session)-[PARTICIPATES]->(Tournament)

Regards,

Cobra

Thank you @Cobra for your answer 🙂

Your refactoring about the relationship between Deck and Tournament is such a great idea. It allows Tournament to optionally register the Deck that a User used for this Tournament (Deck should be optionally registered according to the type of Tournament).

Regards,

Alain

Hello @PastaBolo and happy to help 😊

Do you have more questions?

Regards,

Cobra

The graph has been improved a lot since the last time 😁

I have no more questions at this time. Maybe in the future when I go further in development 😉

Regards,

Alain

I'm happy to hear it 😊

Then, I guess you can close this topic 🙈

Regards,

Cobra