【问题标题】:Add relation to Neo4j with Neo4j.Driver使用 Neo4j.Driver 添加与 Neo4j 的关系
【发布时间】:2023-03-18 12:45:02
【问题描述】:

我是 Neo4j 的新 C# 开发人员。我花了几个星期学习图形概念并尝试了 Cypher。到目前为止,这是一次很好的体验!

我现在尝试通过官方 C# 驱动程序处理来自代码的一些真实数据。我惊讶地发现驱动程序只是 API 的一个包装器,顶部没有真正的 .Net 功能。

在创建节点时,我可以很好地使用这种模式创建 Cypher 语句:

CREATE (:Movie {tmdbId: {tmdbId}, imdbId: {imdbId}, title: {title}, originalTitle: {originalTitle}, collectionInfo: {collectionInfo}, genres: {genres}, releaseDate: {releaseDate}, plot: {plot}, tagline: {tagline}, originalLanguage: {originalLanguage}, tmdbPopularity: {tmdbPopularity}, tmdbVoteAverage: {tmdbVoteAverage}, tmdbVoteCount: {tmdbVoteCount}, budget: {budget}} )

参数集合是从对象自动生成的。它工作正常。但是在创建关系时出现意外错误。

这是我用来创建关系的语句。源节点和目标节点按 Id 查找。

MATCH (s:Person), (t:Movie) WHERE s.personId=35742 AND t.movieId=19404 CREATE (s)-[r:ACTED_IN {order: {order}, character: {character}}]->(t) RETURN r

我收到的错误是:

System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'

参数集合的创建方式与上次相同。正如预期的那样,它包含两个名为“order”和“character”的属性。

我遗漏的语句中是否有一些错误?

    /// <summary>
    /// Add object as node in Neo4j database.
    /// All public properties will automatically be added as properties of the node.
    /// </summary>
    /// <param name="obj">Generic POCO object</param>
    /// <param name="label">Specify type name to be uses. Skip if you are satisfied with object type name.</param>
    public void AddNode(object obj, string label = null)
    {
        using (var session = _driver.Session())
        {
            label = label ?? obj.GetType().Name;
            var parameters = GetProperties(obj);
            var valuePairs = string.Join(", ", parameters.Select(p => $"{p.Key}: {{{p.Key}}}"));
            var statement = $"CREATE (:{label} {{{valuePairs}}} )";
            var result = session.Run(statement, parameters);
            Debug.WriteLine($"{result.Summary.Counters.NodesCreated} {label} node created with {result.Summary.Counters.PropertiesSet} properties");
        }
    }

    public void AddRelation(string sourceNodeName, string sourceIdName, string targetNodeName, string targetIdName, string relationName, object relation, string relationSourceIdName, string relationPropertyIdName)
    {
        using (var session = _driver.Session())
        {
            //MATCH(s:Person), (t:Person)
            //WHERE s.name = 'Source Node' AND t.name = 'Target Node'
            //CREATE(s) -[r:RELTYPE]->(t)
            //RETURN r           
            var parameters = GetProperties(relation);
            var sourceId = parameters[relationSourceIdName];
            var targetId = parameters[relationPropertyIdName];
            var properties = parameters.Where(p => p.Key != relationSourceIdName && p.Key != relationPropertyIdName).ToList();
            var valuePairs = string.Join(", ", properties.Select(p => $"{p.Key}: {{{p.Key}}}"));
            var statement = $"MATCH (s:{sourceNodeName}), (t:{targetNodeName}) WHERE s.{sourceIdName}={sourceId} AND t.{targetIdName}={targetId} CREATE (s)-[r:{relationName} {{{valuePairs}}}]->(t) RETURN r";

            var result = session.Run(statement, properties);
            Debug.WriteLine($"{result.Summary.Counters.RelationshipsCreated} {relationName} relations created with {result.Summary.Counters.PropertiesSet} properties");
        }
    }

    private static Dictionary<string, object> GetProperties(object obj)
    {
        var dictionary = new Dictionary<string, object>();
        foreach (var property in obj.GetType().GetProperties())
        {
            var propertyName = property.Name;
            var value = property.GetValue(obj);

            var array = value as string[];
            if (array != null)
            {
                value = string.Join(",", array);
            }
            if (value is DateTime)
            {
                var dateTime = (DateTime)value;
                value = dateTime.ToString("yyyy-MM-dd");
            }

            dictionary.Add(propertyName.ToCamelCase(), value);
        }
        return dictionary;
    }

【问题讨论】:

  • 你好雅各布!我在我的 Neo4j 浏览器中复制、粘贴并运行了您的查询,并且运行良好!所以我认为您的问题与您的 C# 代码有关,对吧?您能与我们分享生成查询的 C# 代码吗?另外,你在用Neo4jClient library吗?
  • 感谢@BrunoPeres 的快速响应!你是对的,该语句在 Neo4j 浏览器中运行良好,所以我猜它与 C# 包装器有关。我在上面添加了我的方法供您查看。我怀疑这个问题与方括号内的花括号有关,使 Run 方法难以解析语句和参数?
  • Debug.WriteLine(statement); 的输出是什么?
  • 我当然可以做一个解决方法,用内联日期生成完整的语句,但我真的很想避免这种情况。我想参数方法避免“密码注入攻击”是有原因的:)
  • 澄清一下:您的异常发生在AddRelation 函数中,对吧?那么,你能在var statement = $"MATCH (...)var result = session.Run(...) 之间加上一个Debug.WriteLine(statement); 吗?

标签: c# neo4j cypher


【解决方案1】:

布鲁诺让我朝着正确的方向前进! Cypher 和包装器都不是问题。我的错误是过滤参数集合并返回属性列表,而不是将其保存为字典。

调整后的工作方式现在是这样的:

    public void AddRelation(string fromNodeName, string fromIdName, string toNodeName, string toIdName, string relationName, object relation, string relationFromIdName, string relationToIdName)
    {
        using (var session = _driver.Session())
        {
            //MATCH(s:Person), (t:Person)
            //WHERE s.name = 'Source Node' AND t.name = 'Target Node'
            //CREATE(s) -[r:RELATIONTYPE]->(t)
            //RETURN r           
            var parameters = GetProperties(relation);
            var fromIdValue = parameters[relationFromIdName];
            var toIdValue = parameters[relationToIdName];
            var properties = parameters.Where(p => p.Key != relationFromIdName && p.Key != relationToIdName).ToDictionary(p => p.Key, p => p.Value);
            var valuePairs = string.Join(", ", properties.Select(p => $"{p.Key}: {{{p.Key}}}"));
            var statement = $"MATCH (s:{fromNodeName}), (t:{toNodeName}) WHERE s.{fromIdName}={fromIdValue} AND t.{toIdName}={toIdValue} CREATE (s)-[r:{relationName} {{{valuePairs}}}]->(t) RETURN r";
            var result = session.Run(statement, properties);
            Console.WriteLine($"{result.Summary.Counters.RelationshipsCreated} {relationName} relations created with {result.Summary.Counters.PropertiesSet} properties");
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多