Sunday, June 10, 2012

neo4j: Using Cypher Query Language with .NET


After reading the neo4j REST documentation I've created  JSONCypherQuery class with some custom methods in in order to use custom Cypher queries in .NET application.

Creating Classes for Serialization


Below is an example request and response from ne04j REST API documentation


Example request
  • POST http://localhost:7474/db/data/cypher
  • Accept: application/json
  • Content-Type: application/json
{"query": "start x  = node(27) match x -[r]-> n return type(r), n.name?,
n.age?", "params": {}},
Example response
  • 200: OK
  • Content-Type: application/json
{
  "data" : [ [ "know", "him", 25 ], [ "know", "you", null ] ],
  "columns" : [ "type(r)", "n.name?", "n.age?" ]
}

To create a request string formatted the same way as
{"query": "start x  = node(27) match x -[r]-> n return type(r), n.name?, n.age?","params": {}},

we can create a class


class JSONQueryCommand
    {
        [JsonProperty("query")]
        public string Query { get; set; }
        [JsonProperty("params")]
        public string Parameters { get; set; }
    }

and method which posts a request and gets a response as string.

Handling Requests and Responses

The method below transforms the Cypher query string into appropriate web request:


private static string CreateRequest(string query)
        {
            string response = "";
            try
            {
                //Connect
                //http://localhost:7474/db/data/ext/CypherPlugin/graphdb/execute_query
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:7474/db/data/ext/CypherPlugin/graphdb/execute_query");
                req.Method = "POST";
                req.ContentType = "application/json";
                string parameters = null;
                JSONQueryCommand cmd = new JSONQueryCommand();
                cmd.Query = query;
                cmd.Parameters = parameters;
                string json = JsonConvert.SerializeObject(cmd);
                using (var streamWriter = new StreamWriter(req.GetRequestStream()))
                {

                    streamWriter.Write(json);
                }
                var httpResponse = (HttpWebResponse)req.GetResponse();
                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    var responseText = streamReader.ReadToEnd();
                    response = responseText;
                    //Now you have your response.
                    //or false depending on information in the response    
                }
            }
            catch (Exception ex)
            {
            }
            return response;
        }

In order to handle the received string and extract the data we need additional methods. Below is the simple method that extracts scalar value:


public static object GetScalar(string request)
        {
            string response = CreateRequest(request);
            var joResponse = JObject.Parse(response);
            var jaData = (JArray)joResponse["data"];
            var dataArray = jaData.First();
            var firstDataElement = dataArray.First();
            JValue jResult = (JValue)firstDataElement;
            object result = jResult.Value;
            return result;
        }

Example

After creating these methods we can simply use custom Cypher queries.

object response = JSONCypherQuery.GetScalar("start a = node(1) MATCH (a)--(b) return count(b);");
int neighborsCount= Convert.ToInt32(response);


The code block

 req.Method = "POST";
                req.ContentType = "application/json";
                string parameters = null;
                JSONQueryCommand cmd = new JSONQueryCommand();
                cmd.Query = query;
                cmd.Parameters = parameters;
                string json = JsonConvert.SerializeObject(cmd);


creates a web rquest with content

{"query":"start a = node(1) MATCH (a)--(b) return count(b);","params":null}

which is sent to server and if we know what kind of data are we expecting to receive from server, we can create an appropriate parsing/deserializing method. For the example query the result is scalar and the method GetScalar extracts it from response string.




No comments:

Post a Comment