加载具有关系的实体Neo4jClient

时间:2015-07-02 15:45:48

标签: c# neo4j neo4jclient

我有一个带有以下实体的Neo4J Graph-Database:

(游戏) - [:具有] - GT;(gamePlayerMapping) - [:mappingFor] - GT;播放器

所以实际上我有一个实体游戏和一个实体玩家。这些实体之间存在着多对多的关系。

实体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-Objects列表
  • 播放器对象列表

所以这是我的问题:

如何知道Players-List中的哪些Player-Objects属于相应列表中的哪个GamePlayerMapping?

我可以假设索引0处的玩家属于索引0处的映射,依此类推?听起来很脏。

当然,如果有这样的情况,这种方法将不再适用:

(使用实体) - [:的hasMany] - GT;(ENTITY2) - [:的hasMany] - GT;(ENTITY3)

1 个答案:

答案 0 :(得分:2)

我有3种方法,其中没有一种是amazeballs。

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而另一个获得它的玩家等。

<强>积极因素

  • 很容易知道地图/玩家配对/分组。

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>()
    });

<强>否定

  • 你返回Game n次,这是一个开销。
  • 您必须将结果解析为可以使用的格式。

<强>积极因素

  • 如果没有CollectAs每个Mapping,则会加入Player配对,因此您知道它们匹配。

3。添加&#39; PlayerIds&#39;收集到GamePlayerMapping

您仍然可以执行原始查询,但可以通过从映射中提取播放器ID来将结果解析为所需的格式。

<强>否定

  • 您必须编辑实际的类,然后确保在添加添加映射的播放器时,确保映射列表保持最新等等。

<强>积极因素

  • 嗯 - 你可以找出哪个映射有哪个玩家。

很多东西都归结为你需要的那种性能。我认为第一个选项是最不好的,但你可能会发现2个调用太多了。第二个选项是一个查询,但返回Game n次,因此对于3个玩家,你将游戏返回3次,并且对于映射,你可以将其返回到玩家的次数。那个映射。因此,就数据传输而言 - 它效率不高。

第三种选择虽然最适合通过电线传输数据 - 但这将是有问题的,并且确保它总是正确的要复杂得多。

我个人选择选项1 :/