2017-11-22 2 views
0

私はNeo4jを初めて使うC#開発者です。私はグラフのコンセプトを学び、Cypherを試して2、3週間過ごしました。それはこれまでのところ良い経験です!Neo4j.DriverでNeo4jとの関係を追加する

公式のC#ドライバを使用してコードからの実際のデータで作業しようとしました。私はドライバが実際の.Net機能を一切持っていないAPIのラッパーにすぎないことに驚きました。

私はこのパターンとサイファー文を作成するために、細かな管理対象ノードの作成:

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"という2つのプロパティを期待通りに保持します。

私が紛失しているという記述に何らかのエラーがありますか?

/// <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; 
    } 
+0

こんにちはヤコブ!私はNeo4jブラウザにあなたの質問をコピーし、貼り付けて実行し、うまくいった!だからあなたの質問はあなたのC#コードに関係していると思いますよね?私たちとクエリを生成するC#コードを共有できますか?また、[Neo4jClientライブラリ](https://github.com/Readify/Neo4jClient)を使用していますか? –

+0

速い応答のために@BrunoPeresに感謝します!あなたは正しいです、ステートメントはNeo4jブラウザで正常に動作するので、C#ラッパーに関係していると思います。あなたのレビューのために上記の方法を追加しました。私はこの問題が、角括弧の中の中括弧に関係していると考えているので、Runメソッドが文とパラメータを解析するのは難しいですか? –

+0

'Debug.WriteLine(statement);'の出力は何ですか? –

答えて

0

ブルーノが正しい方向に私を置いてくれました!それは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"); 
     } 
    }