2014-11-23 2 views
1

Может ли любой орган помочь мне преобразовать этот запрос Cypher в neo4jclient?Neo4jClient Union

MATCH (o)-[r]-(post:Post)-[:HAS_MentionedUsers]->(assignee1307989068:User), 
WHERE (assignee1307989068.UserName = "mhs") 
RETURN post,o,r 
UNION 
MATCH (o)-[r]-(post:Post)-[:HAS_HashTags]-> (Hashtag1841024507:HashTag) 
WHERE (Hashtag1841024507.Value = "myTag") 
RETURN post,o,r 

Есть ли идеи, как создать выше Cypher запрос динамически на основе пользовательского ввода, который whould быть «MHS» и «MyTag» в C# и neo4jClient?

Вот что я havetried до сих пор:

Метод поиска будет получить слово для поиска и разметить его, то метод BuildPostQueystring добавит каждую часть шифровальщика запроса.

public Object Search(string searchterm) 
    { 
     List<string> where = new List<string>(); 
     var tokenizedstring = searchterm.Split(' '); 
     var querystring = new StringBuilder(); 
     int unionCount = 0; 
     var q = new CypherFluentQuery(_graphClient) as ICypherFluentQuery; 

     foreach (var t in tokenizedstring) 
     { 
      _commandService.BuildPostQueystring(t, ref querystring, ref where); 

      if (querystring[querystring.Length - 1] == ',') 
       querystring = querystring.Remove(querystring.Length - 1, 1); 

      if (unionCount > 0) 
       q = q.Union(); 


      q = q.Match(querystring.ToString()); 

      unionCount++; 

      int i = 1; 

      if (where.Count > 0) 
       q = q.Where(where[0]); 

      while (i < where.Count) 
      { 
       q = q.OrWhere(where[i]); 
       i++; 

      } 

      q = q.Return((post, nodes) => new { Post = post.As<Node<string>>(), Nodes = nodes.As<Node<string>>() }) 
      .OrderBy("post.creationDate"); 

      where.Clear(); 
      querystring.Clear(); 
     } 

     //var rq = q.Return((post, o) => new {Person = post.As<Node<string>>(), Dog = o.As<Node<string>>()}) 
     // .OrderBy("post.creationDate"); 

     var x = (q as CypherFluentQuery<dynamic>).Results; 

     return x.ToList(); 
    } 

Другой метод, добавить часть запроса как пар:

public void BuildPostQueystring(string token, ref StringBuilder sb, ref List<string> whereConditions) 
    { 
     string querystring = "(nodes)-[r]-(post:Post)-[:HAS_{0}]->({1}:{2})"; 
     string wherestring = "({0}.{1} = \"{2}\")"; 
     if (token.StartsWith("#")) 
     { 
      int hash = token.GetHashCode(); 
      if (hash < 0) 
       hash = hash*-1; 

      string paramName = "Hashtag" + hash; 
      var str = string.Format(querystring, "HashTags", paramName, "HashTag"); 
      var tvalue = token.Replace("#", ""); 
      //query = query.AndWhere((HashTag hashTag) => hashTag.Value == tvalue); 
      sb.Append(str); 
      whereConditions.Add(string.Format(wherestring, paramName, "Value", tvalue)); 
     } 

     else if (token.StartsWith("+")) 
     { 

      int hash = token.GetHashCode(); 
      if (hash < 0) 
       hash = hash * -1; 
      string paramName = "team" + hash; 

      var str = string.Format(querystring, paramName, "MentionedTeam","Team"); 
      sb.Append(str); 
      var tvalue = token.Replace("+", ""); 
      whereConditions.Add(string.Format(wherestring,paramName, "Name", tvalue)); 
     } 

     else if (token.StartsWith("@")) 
     { 
      int hash = token.GetHashCode(); 
      if (hash < 0) 
       hash = hash * -1; 

      string paramName = "assignee" + hash; 

      var str = string.Format(querystring, "MentionedUsers", paramName, "User"); 
      sb.Append(str); 
      var tvalue = token.Replace("@", ""); 
      whereConditions.Add(string.Format(wherestring, paramName,"UserName", tvalue)); 
     } 
     else if (token.StartsWith("by")) 
     { 
      int hash = token.GetHashCode(); 
      if (hash < 0) 
       hash = hash * -1; 

      string paramName = "author" + hash; 

      var str = string.Format(querystring, "Author", paramName, "User"); 
      sb.Append(str); 

      var tvalue = token.Replace("by:", ""); 
      whereConditions.Add(string.Format(wherestring, paramName, "UserName", tvalue)); 

     } 
     else if (token.Contains("\\")) 
     { 
      foreach (var dt in GetLocalDateTokens(_dateTimeTokens)) 
      { 
       int hash = token.GetHashCode(); 
       if (hash < 0) 
        hash = hash * -1; 

       string paramName = "dueDate" + hash; 

       if (token.ToLower() == dt.Text.ToLower()) 
       { 
        var neodate = new NeoDateTime(); 
        neodate.Year = dt.GetDate.Year; 
        neodate.Month = dt.GetDate.Month; 
        neodate.Day = dt.GetDate.Day; 
        neodate.TimeStamp = long.Parse(dt.GetDate.ToString("HHmmss")); 
        neodate.DateStamp = long.Parse(dt.GetDate.ToString("yyyyMMdd")); 
        neodate.DateTimeStamp = long.Parse(dt.GetDate.ToString("yyyyMMddHHmmss")); 
        var str = string.Format(querystring, "DueDates", paramName, "NeoDateTim"); 
        sb.Append(str); 
        var tvalue = token.Replace("by:", ""); 
        whereConditions.Add(string.Format(wherestring, "DateStamp", paramName, tvalue)); 

       } 
      } 
     } 
     else 
     { 
      //MATCH (n) 
      //WHERE n.name =~ 'Tob.*' 
      //RETURN n 
      var wherestr = "({0}.{1} =~ '{2}.*')"; 
      //string wherestring = "({0}.{1} = \"{2}\")"; 
      //string querystring = "(post:Post)-[:HAS_{0}]->({1}:{2})"; 
      string paramName = "post" + token + GetHashCode(); 
      string qs = "(post:Post)"; 
      var str = string.Format(qs, paramName); 
      sb.Append(str); 
      whereConditions.Add(string.Format(wherestr, "post", "Text", token)); 

     } 
     if(sb.Length>0) 
      sb.Append(","); 


    } 

Моя первая проблема заключается в том, чтобы получить результат как д не имеет метод результата, и я не могу бросить его в анонимный тип ?!

+0

Хорошо, что вы пробовали? –

+0

То, что я пытался как пар: 1- я разметить вход поиска 2 Строить Match Строка на сообщение 3 добавить где положение в конце строки 4- Выполнение запроса 5- получения результата назад. Проблема, которую я имею до сих пор, заключается в том, что я теряю все другие связанные узлы в POST, который я пытаюсь выполнить Capture by (o) - [r] также результат будет другим, если я добавлю предложение where и или их вместе, или если я объединяю каждый раздел результатов. –

ответ

2

ОК, во-первых, причина q не метод Results потому, что вплоть до добавления Return вызова у вас есть только ICypherFluentQuery, поэтому если у вас есть:

var query = client.Cypher.Match("(n:Post)"); 

query будет типа ICypherFluentQuery, который не имеет метод Results после того, как вы добавите Return заявление:

var query = client.Cypher.Match("(n:Post)").Return(n => n.As<Post>()); 

вы найдете query сейчас: ICypherFluentQuery<Post>. Поэтому, прежде чем добавить .Return заявление, вам необходимо присвоить другой переменной:

var query = client.Cypher.Match("(n:Post)"); 
var retQuery = query.Return(n => n.As<Post>()); 
var results = retQuery.Results; 

Вторая часть, фактический запрос.

Это не совсем понятно, что вы пытаетесь сделать с вашим кодом, у вас есть много, но код запроса (на мой взгляд) должно выглядеть примерно так:

private void GetResults(string username, string tagValue) 
{ 
    var query = Client.Cypher 
     .Match("(o)-[r]-(post:Post)-[:HAS_MentionedUsers]->(assignee:User)") 
     .Where((User assignee) => assignee.UserName == username) 
     .Return((post, o, r) => new {Post = post.As<Post>(), O = o.As<object>(), R = r.As<RelationshipInstance<object>>()}) 
     .Union() 
     .Match("(o)-[r]-(post:Post)-[:HAS_MentionedUsers]->(hashTag:HashTag)") 
     .Where((HashTag hashTag) => hashTag.Value == tagValue) 
     .Return((post, o, r) => new {Post = post.As<Post>(), O = o.As<object>(), R = r.As<RelationshipInstance<object>>()}); 

    var res = query.Results.ToList(); 
} 

PS: Я понятия не имею, какой тип o, поэтому я использовал object как заполнитель

Если по какой-то причине вам нужно использовать эти имена assignee1307989068 и т.д., как вы строите до эпической запроса, то where стал бы что-то вроде:

/* MATCH */ 
.Where("assignee123.Value == {assignee123Param}") 
.WithParam("assignee123", username) 
/* RETURN */ 

Если вы можете, я бы с первой версией, как это типобезопасно и легче понять.

+0

Дорогой Крис, я понимаю, что это за точка. причиной моего сложного кода является то, что я получаю пользовательский ввод, украшенный каким-то причудливым символом вроде (#, @, +, /), и из этого символа я могу найти, какой узел должен быть включен в запрос cypher. это не всегда хэштег и Пользователь. Я понимаю, что результат будет доступен, когда fluentcypherQuery получит возвращаемый тип бит T, который, как я думаю, должен быть способом, которым мы получаем только результат json из neo4jclient. –

+0

Я нашел это сообщение о том, что вы помогли мне вернуть результат json: http://stackoverflow.com/questions/21860074/casting-nodes-of-an-unknown-type , но большое вам спасибо за замечательный вклад в эти темы. –

Смежные вопросы