我有一个带有以下实体的Neo4J Graph-Database:
(游戏) - [:具有] - GT;(gamePlayerMapping) - [:mappingFor] - GT;播放器
所以实际上我有一个实体游戏和一个实体玩家。这些实体之间存在着多对多的关系。
实体GamePlayerMapping也可以链接到其他实体。这就是为什么它必须是一个节点本身。
在我的c#代码中,我有三个相应的类:
现在我想加载一个包含所有相应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;
查询工作正常,我得到一个具有以下属性的对象:
所以这是我的问题:
如何知道Players-List中的哪些Player-Objects属于相应列表中的哪个GamePlayerMapping?
我可以假设索引0处的玩家属于索引0处的映射,依此类推?听起来很脏。
当然,如果有这样的情况,这种方法将不再适用:
(使用实体) - [:的hasMany] - GT;(ENTITY2) - [:的hasMany] - GT;(ENTITY3)
答案 0 :(得分:2)
我有3种方法,其中没有一种是amazeballs。
在这个游戏中,首先获得游戏,然后是映射:
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
而另一个获得它的玩家等。<强>积极因素强>
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>()
});
<强>否定强>
Game
n次,这是一个开销。 <强>积极因素强>
CollectAs
每个Mapping
,则会加入Player
配对,因此您知道它们匹配。GamePlayerMapping
您仍然可以执行原始查询,但可以通过从映射中提取播放器ID来将结果解析为所需的格式。
<强>否定强>
<强>积极因素强>
很多东西都归结为你需要的那种性能。我认为第一个选项是最不好的,但你可能会发现2个调用太多了。第二个选项是一个查询,但返回Game
n次,因此对于3个玩家,你将游戏返回3次,并且对于映射,你可以将其返回到玩家的次数。那个映射。因此,就数据传输而言 - 它效率不高。
第三种选择虽然最适合通过电线传输数据 - 但这将是有问题的,并且确保它总是正确的要复杂得多。
我个人选择选项1 :/