2017-11-22 1 views
0

저는 Neo4j를 처음 접하는 C# 개발자입니다. 저는 2 주 동안 그래프 개념을 배우고 Cypher를 사용해 보았습니다. 그것은 지금까지 좋은 경험입니다!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 

I 나타나는 오류는 다음과 같습니다

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

매개 변수 컬렉션과 같은 방식으로 마지막으로 작성됩니다. 예상대로 "주문"및 "문자"라는 두 개의 속성을 보유하고 있습니다.

누락 된 부분에 오류가 있습니까?

/// <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# wrapper와 관련이 있다고 생각한다. 위의 방법을 귀하의 검토에 추가했습니다. 그 문제는 중괄호 안에있는 중괄호와 관련이있어서 Run 메서드가 문과 매개 변수를 구문 분석하기가 어렵다고 생각합니다. –

+0

'Debug.WriteLine (statement); '의 결과는 무엇입니까? –

답변

0

브루노가 올바른 방향으로 나를 설정했습니다! 그것은 사이퍼와 래퍼 모두에게 문제가되지 않았습니다. 내 실수는 매개 변수 컬렉션을 필터링하고 사전으로 유지하는 대신 속성 목록을 반환하는 것이 었습니다.

조정 된 작업 방법은 이제 다음과 같습니다

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