【问题标题】:Load Entities with Relationsships Neo4jClient加载具有关系的实体 Neo4jClient
【发布时间】:2015-07-03 17:40:48
【问题描述】:

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

(game)-[:has]->(gamePlayerMapping)-[:mappingFor]->Player

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

实体 GamePlayerMapping 也可以链接到其他实体。这就是为什么它必须是一个节点本身。

在我的 c# 代码中,我有三个对应的类:

  • Game.cs
  • Player.cs
  • GamePlayerMapping.cs

现在我想加载一个包含所有相应 gamePlayerMappings 和相应 Players 的游戏。

使用 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)

【问题讨论】:

    标签: c# neo4j neo4jclient


    【解决方案1】:

    我有 3 种方法,没有一个是惊人的。

    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 每个 MappingPlayer 配对就会加入,因此您知道它们匹配。

    3。将“PlayerIds”集合添加到 GamePlayerMapping

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

    否定

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

    积极因素

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

    很大程度上取决于您需要的性能。我认为第一个选项是最不坏的,但你可能会发现这 2 个电话太多了。第二个选项是一个查询,但返回Game n 次,因此对于 3 个玩家,您将游戏返回 3 次,对于映射,您将返回与该映射中的玩家一样多的次数。因此,就通过网络传输的数据而言 - 它不是很有效。

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

    我个人会选择选项 1 :/

    【讨论】:

    • 谢谢克里斯。现在我将采用第一种方法,看看它如何影响应用程序的性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 2013-02-26
    • 1970-01-01
    相关资源
    最近更新 更多