加载具有关系的实体 Neo4jClient

Load Entities with Relationsships Neo4jClient

我有一个包含以下实体的 Neo4J 图形数据库:

(游戏)-[:has]->(gamePlayerMapping)-[:mappingFor]->玩家

所以其实我有一个实体游戏和一个实体播放器。这些实体之间存在多对多关系。

实体 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 处的映射等等吗?听起来很脏。

当然,如果遇到这样的情况,这种方法将不再有效:

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

否定

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

正面

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

3。将 'PlayerIds' 集合添加到 GamePlayerMapping

您仍然可以执行原始查询,但可以通过从映射中提取玩家 ID 将结果解析为您想要的格式。

否定

  • 您必须编辑您的实际 class,然后确保在添加玩家时添加映射,确保映射列表保持最新,等等

正面

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

很大程度上取决于您需要的性能。我认为第一个选项最不糟糕,但您可能会发现这 2 个调用太多了。第二个选项是一次查询,但是 returns Game n 次,所以对于 3 个玩家,你将游戏返回 3 次,而对于映射,你将获得尽可能多的返回次数是该映射中的玩家。因此,就通过网络传输的数据而言,效率不高。

第三个选项虽然最适合通过网络传输数据 - 但会出现问题,而且要确保它始终正确要复杂得多。

我个人会选择选项 1 :/