加载具有关系的实体 Neo4jClient
Load Entities with Relationsships Neo4jClient
我有一个包含以下实体的 Neo4J 图形数据库:
(游戏)-[:has]->(gamePlayerMapping)-[:mappingFor]->玩家
所以其实我有一个实体游戏和一个实体播放器。这些实体之间存在多对多关系。
实体 GamePlayerMapping 也可以链接到其他实体。这就是为什么它必须是一个节点本身。
在我的c#代码中我有三个对应的类:
- Game.cs
- Player.cs
- GamePlayerMapping.cs
现在我想加载一个游戏,其中包含所有相应的 gamePlayerMappings 和相应的玩家。
使用 Neo4JClient,这就是我的查询代码:
var x = _client.Cypher
.Match("(game:Game {GameId: '" + id + "'})")
.OptionalMatch("(game)-[has]->(gamePlayerMapping:GamePlayerMapping)-[:mappingFor]->(player:Player)")
.Return((game, gamePlayerMapping, player) => new
{
Game = game.As<Game>(),
Mappings = gamePlayerMapping.CollectAs<GamePlayerMapping>(),
Players = player.CollectAs<Player>(),
}
)
.Results;
查询工作正常,我得到一个具有以下属性的对象:
- 一个游戏对象
- GamePlayerMapping 对象列表
- 玩家对象列表
所以这是我的问题:
我如何知道 Players-List 中的哪些 Player-Objects 属于相应列表中的哪个 GamePlayerMapping?
我可以假设索引 0 处的玩家属于索引 0 处的映射等等吗?听起来很脏。
当然,如果遇到这样的情况,这种方法将不再有效:
(entity1)-[:hasMany]->(entity2)-[:hasMany]->(entity3)
我有 3 种方法,none 其中很神奇。
1。一分为二
在这个中,先获取游戏,然后获取映射:
var gameQuery = new CypherFluentQuery(_client)
.Match("(g:Game {GameId: 1})")
.Return(g => g.As<Game>());
var mappingQuery = new CypherFluentQuery(_client)
.Match("(g:Game {GameId: 1})")
.OptionalMatch("(g)-[:has]->(gpm:GamePlayerMapping)-[:mappingFor]->(p:Player)")
.Return((gpm, p) => new
{
Mappings = gpm.As<GamePlayerMapping>(),
Players = p.CollectAs<Player>()
});
这为您提供了您期望的映射和分组。
否定
- 显而易见 - 两个查询 - 一个获取
Game
另一个获取它的玩家等
正面
- mapping/playerpairing/grouping.
很容易知道
2。不要 CollectAs
基本上,接受您的查询,但删除 CollectAs
位:
var query = new CypherFluentQuery(Client)
.Match("(g:Game {GameId: 1})")
.OptionalMatch("(g)-[:has]->(gpm:GamePlayerMapping)-[:mappingFor]->(p:Player)")
.Return((g, gpm, p) => new
{
Game = g.As<Game>(),
Mapping = gpm.As<GamePlayerMapping>(),
Player = p.As<Player>()
});
否定
- 你return
Game
n次,这是一个开销。
- 您必须将结果解析为您可以使用的格式。
正面
- 如果没有
CollectAs
,每个 Mapping
、Player
配对都会加入,因此您知道它们匹配。
3。将 'PlayerIds' 集合添加到 GamePlayerMapping
您仍然可以执行原始查询,但可以通过从映射中提取玩家 ID 将结果解析为您想要的格式。
否定
- 您必须编辑您的实际 class,然后确保在添加玩家时添加映射,确保映射列表保持最新,等等
正面
- 嗯 - 你可以算出哪个映射有哪个玩家。
很大程度上取决于您需要的性能。我认为第一个选项最不糟糕,但您可能会发现这 2 个调用太多了。第二个选项是一次查询,但是 returns Game
n 次,所以对于 3 个玩家,你将游戏返回 3 次,而对于映射,你将获得尽可能多的返回次数是该映射中的玩家。因此,就通过网络传输的数据而言,效率不高。
第三个选项虽然最适合通过网络传输数据 - 但会出现问题,而且要确保它始终正确要复杂得多。
我个人会选择选项 1 :/
我有一个包含以下实体的 Neo4J 图形数据库:
(游戏)-[:has]->(gamePlayerMapping)-[:mappingFor]->玩家
所以其实我有一个实体游戏和一个实体播放器。这些实体之间存在多对多关系。
实体 GamePlayerMapping 也可以链接到其他实体。这就是为什么它必须是一个节点本身。
在我的c#代码中我有三个对应的类:
- Game.cs
- Player.cs
- GamePlayerMapping.cs
现在我想加载一个游戏,其中包含所有相应的 gamePlayerMappings 和相应的玩家。
使用 Neo4JClient,这就是我的查询代码:
var x = _client.Cypher
.Match("(game:Game {GameId: '" + id + "'})")
.OptionalMatch("(game)-[has]->(gamePlayerMapping:GamePlayerMapping)-[:mappingFor]->(player:Player)")
.Return((game, gamePlayerMapping, player) => new
{
Game = game.As<Game>(),
Mappings = gamePlayerMapping.CollectAs<GamePlayerMapping>(),
Players = player.CollectAs<Player>(),
}
)
.Results;
查询工作正常,我得到一个具有以下属性的对象:
- 一个游戏对象
- GamePlayerMapping 对象列表
- 玩家对象列表
所以这是我的问题:
我如何知道 Players-List 中的哪些 Player-Objects 属于相应列表中的哪个 GamePlayerMapping?
我可以假设索引 0 处的玩家属于索引 0 处的映射等等吗?听起来很脏。
当然,如果遇到这样的情况,这种方法将不再有效:
(entity1)-[:hasMany]->(entity2)-[:hasMany]->(entity3)
我有 3 种方法,none 其中很神奇。
1。一分为二
在这个中,先获取游戏,然后获取映射:
var gameQuery = new CypherFluentQuery(_client)
.Match("(g:Game {GameId: 1})")
.Return(g => g.As<Game>());
var mappingQuery = new CypherFluentQuery(_client)
.Match("(g:Game {GameId: 1})")
.OptionalMatch("(g)-[:has]->(gpm:GamePlayerMapping)-[:mappingFor]->(p:Player)")
.Return((gpm, p) => new
{
Mappings = gpm.As<GamePlayerMapping>(),
Players = p.CollectAs<Player>()
});
这为您提供了您期望的映射和分组。
否定
- 显而易见 - 两个查询 - 一个获取
Game
另一个获取它的玩家等
正面
- mapping/playerpairing/grouping. 很容易知道
2。不要 CollectAs
基本上,接受您的查询,但删除 CollectAs
位:
var query = new CypherFluentQuery(Client)
.Match("(g:Game {GameId: 1})")
.OptionalMatch("(g)-[:has]->(gpm:GamePlayerMapping)-[:mappingFor]->(p:Player)")
.Return((g, gpm, p) => new
{
Game = g.As<Game>(),
Mapping = gpm.As<GamePlayerMapping>(),
Player = p.As<Player>()
});
否定
- 你return
Game
n次,这是一个开销。 - 您必须将结果解析为您可以使用的格式。
正面
- 如果没有
CollectAs
,每个Mapping
、Player
配对都会加入,因此您知道它们匹配。
3。将 'PlayerIds' 集合添加到 GamePlayerMapping
您仍然可以执行原始查询,但可以通过从映射中提取玩家 ID 将结果解析为您想要的格式。
否定
- 您必须编辑您的实际 class,然后确保在添加玩家时添加映射,确保映射列表保持最新,等等
正面
- 嗯 - 你可以算出哪个映射有哪个玩家。
很大程度上取决于您需要的性能。我认为第一个选项最不糟糕,但您可能会发现这 2 个调用太多了。第二个选项是一次查询,但是 returns Game
n 次,所以对于 3 个玩家,你将游戏返回 3 次,而对于映射,你将获得尽可能多的返回次数是该映射中的玩家。因此,就通过网络传输的数据而言,效率不高。
第三个选项虽然最适合通过网络传输数据 - 但会出现问题,而且要确保它始终正确要复杂得多。
我个人会选择选项 1 :/