Reputation: 3
I just started programming in R, neo4j and R-neo4j so please be indulgent if my question is trivial.
I have created following database (please confer the attached photo) [1] using R-neo4j and the following R Project code [2].
The database contains the outcome of computer game matches between four players. The dataset consists of four nodes, player 1 to player 4. The nodes are connected via the relationship "defeats", which indicates the outcome of the matches. There are two label entries attached to each relationship containing the following data: judge, game.
From the graph database using Cypher queries, I want to extract data in the following form (please confer the picture in [1]):
Winning player Loosing player Game Judge
player 1 player 4 Starcraft player 2
player 1 player 4 LOL player 3
player 4 player 1 LOL player 2
player 1 player 4 Starcraft player 3
player 1 player 2 LOL player 3
player 2 player 1 LOL player 4
player 4 player 1 Starcraft player 4
I want to make a query (preferred in the R-neo4j environment) to the graph database, where the input is "player 1" and the table above is returned.
I hope that my question is clear and someone can help me with this.
Have a good day.
Christian
[2] The R (Rneo4j) code:
clear(graph)
Y
player1 = createNode(graph,"user",ID="Player 1",male=T)
player2 = createNode(graph,"user",ID="Player 2",male=T)
player3 = createNode(graph,"user",ID="Player 3",male=F)
player4 = createNode(graph,"user",ID="Player 4",male=F)
addConstraint(graph,"user","ID")
rel1 = createRel(player1,"defeats",player4)
rel2 = createRel(player1,"defeats",player4)
rel3 = createRel(player4,"defeats",player1)
rel4 = createRel(player1,"defeats",player4)
rel5 = createRel(player1,"defeats",player2)
rel6 = createRel(player2,"defeats",player1)
rel7 = createRel(player3,"defeats",player1)
rel1 = updateProp(rel1, game = "Starcraft", judge = "Player 2")
rel2 = updateProp(rel2, game = "League of Legends", judge = "Player 3")
rel3 = updateProp(rel3, game = "League of Legends", judge = "Player 2")
rel4 = updateProp(rel4, game = "Starcraft", judge = "Player 3")
rel5 = updateProp(rel5, game = "League of Legends", judge = "Player 3")
rel6 = updateProp(rel6, game = "League of Legends", judge = "Player 4")
rel7 = updateProp(rel7, game = "Starcraft", judge = "Player 4")
Upvotes: 0
Views: 184
Reputation: 1304
Looking at your graph, it kind of hits me of not having the right structure. Even though every scenario might be different, it is always good to consider what happens when you add MUCH more data. Can your model handle it?
For example, you are using relationships to represent results of games, which then of course requires attributes to store the judge and the games. Game names actually look like tournament games to me, but you'll know what works better. When storing the player and tournament names, you end up having a lot of repetition because the same names and players appear everywhere.
If you continue to add results between players you will end up with many relationships and the possibilities for error and repetition keep growing.
What can you do in order to improve your model then? Think of your basic relationship as a starting point but now it has outgrown the original requirement: you can introduce nodes for tournaments and nodes for games; keep relationships for storing the roles of the players within a game and so on. There is always more than one way to do it (TIMTOWTDI).
Given that a picture is worth a thousand words, look at the improved model here:
You see how it is also easier to add additional properties to the corresponding nodes or relationships in the model.
In order to produce your desired table with results, you then can use:
MATCH
(g:Game)-[:WINNER]->(w:Player),
(g)-[:LOSER]->(l:Player),
(g)-[:JUDGE]->(j:Player),
(g)<-[:HAS_GAMES]-(t:Tournament)
WHERE
w.name = 'Player 1' OR l.name = 'Player 1'
RETURN
w.name AS 'Winning Player',
l.name AS 'Losing Player',
t.name AS 'Game',
j.name AS 'Judge'
and adapt for R as suggested by Nicole. If you pretend to add lots of data, I think this structure will adapt better to your needs, and you can also explore different ways of querying for the same data, as you can now start with the tournaments or explore games directly.
Upvotes: 0
Reputation: 7790
A couple things. If you want to use clear(graph)
without having to type "Y", you can use clear(graph, input=F)
. Also, if you weren't aware, you can set properties on relationships when you create them:
rel1 = createRel(player1, "defeats", player4, game="Starcraft", judge="Player 2")
To answer the question, I'd do this:
getDataForPlayer = function(name) {
query = "
MATCH (winner:user)-[game:defeats]->(loser:user)
WHERE winner.ID = {name} OR loser.ID = {name}
RETURN winner.ID AS `Winning Player`,
loser.ID AS `Losing Player`,
game.game AS Game,
game.judge AS Judge
"
return(cypher(graph, query, name=name))
}
getDataForPlayer("Player 1")
Output:
Winning Player Losing Player Game Judge
1 Player 4 Player 1 League of Legends Player 2
2 Player 2 Player 1 League of Legends Player 4
3 Player 3 Player 1 Starcraft Player 4
4 Player 1 Player 2 League of Legends Player 3
5 Player 1 Player 4 Starcraft Player 2
6 Player 1 Player 4 League of Legends Player 3
7 Player 1 Player 4 Starcraft Player 3
Upvotes: 1