Windows 8 Let’s Boot Up

This post comes from windows 8 developer preview.I fired up a virtual machine using the virtual box (virtual pc and vmware failed).Virtual box will require a few tricks when you fire it up for the first time.Details will follow in the next blog.

Advertisements

Freebase Query with C# : Level 2

In my previous post I wrote about how to query Freebase using MQL .In this blog post I will try and construct a slightly more complex query for Freebase.Freebase has name:value pairs which we can query and get our desired result.
We start with our simple query and make a little more complex.

class Question
{
public String type { get; set; }
public String name { get; set; }
public Dictionary album { get; set; }
public Question()  
{
 this.album = new Dictionary();}
}

Next,Just new up the Question instance with some data.


Question q = new Question();
q.type = "/music/artist";
q.name = null;q.album.Add("name",null);
q.album.Add("name~=","greatest hits");
q.album.Add("optional",true);

Now,begin the task to convert the Question object into a Json object for the query.The idea I used was to take in a object as a parameter and then iterate over all the properties using reflection (I Will talk more about it in the next post).


class ParseToJsonString 
{

 private StringBuilder sb;
 private Type type;
 private PropertyInfo[] propinfo;
 private PropertyInfo currentProperty;
 public String JsonString { get; set; }
 public ParseToJsonString(Object sender)
{
 this.sb = new StringBuilder();
 this.type = sender.GetType();
 this.propinfo = this.type.GetProperties();
 this.JsonString = "";
 toJsonString(sender);
//remain agnostic to the object being passed in as a parameter,get all the properties using reflection</pre>
private void toJsonString(Object sender){
     sb.Append("{");
     foreach (PropertyInfo p in propinfo){
      // Console.WriteLine(p.PropertyType);
         currentProperty = p;
         sb.AppendLine();
        if (p.PropertyType == typeof(Int32) || p.PropertyType == typeof(Double)
           || p.PropertyType == typeof(float) || p.PropertyType == typeof(bool)){
             handlePrimitive(sender, p);}
         else if (p.PropertyType == typeof(String))
           {
             handle String(sender, p);
           }

In the snippet above we loop through the properties and handle them for parsing according to their type.
For more complex types like list,dictionary etc. we have to adopt a similar approach.
I have written the method considering the for collections as String(since I am concentrating on Freebase),
this can be easily converted to handle all of the types.The output we get is as follows:-


{
 "type":"/music/artist",
 "name":null,
 "album":[{
             "name":null,
             "name~=":"greatest hits",
             "optional":<del datetime="2011-09-18T14:05:03+00:00">True</del>true
           }]
}

We can use this parser(with some improvements) to develop a wrapper and build an even more complicated query using the reserved key words of Freebase to have sorting,filtering,limiting etc..
Update:- the “optional” parameter must have a value of boolean in lower case ,True will raise an error.Freebase expects it to be true.
The entire class is available below for download.
Download ParseToJsonString

How to query Freebase from c#…

Freebase is a great source of open data,we can query it using
MQL.I will try and show how we can quickly query it to get some data.

Firstly I used .net 4 ,visual studio sp1, nuget(Awesome package management) and two cool packages(details about the packages follow).

The objective is to retrieve a set of albums of “The Police”.


class Album
 {
public String type {get;set;}
public String name {get;set;}
public String[] album { get; set; }
}

Notice that we need to get a set of “albums” for the artist specified by “name”.The search criteria also needs a domain to look into which we will specify through “type”.

Next,We need to set up a Json Object and send it across as a parameter over HTTP.We can consume the Rest based service through a wonderful nuget packageRestSharp.


var client = new RestClient();
client.BaseUrl = ”https://www.freebase.com/api/service/mqlread”;
var request = new RestRequest(Method.GET);

Now,we need to create a album object to pass along with the request.


Album thepolice = new Album{type = ”/music/artist”,name = ”The Police” };

Next we need to serialize the object,so we will use NewtonSoft(which you won’t need to install since it is dependency for the RestSharp package and nuget will fetch it beforehand).

Freebase follows the fill in the blanks approach to return data i.e. for the following MQL query

Freebase will return results where ever it finds null(name,guid) or [](/location/location/containedby,/location/place_with_neighborhoods/neighborhoods).
The places with null will be substituted with a single result and [] will be substituted with a set of results.

So we now have to convert our album object into a Json Object and attach it to our request.Initially we add the following method to the Album class.


class Album {
public String type {get;set;}
public String name {get;set;}
public String[] album { get; set; }
public String ToJsonString()
{
  return "{" +  JsonConvert.SerializeObject(“query”, Formatting.Indented) + ":" +
  JsonConvert.SerializeObject(this, Formatting.Indented) + "\n" +   "}";}
}

Album thepolice = new Album{type = ”/music/artist”,name = ”The Police” };

Console.WriteLine(thepolice.ToJsonString());//Just for debug purposes
request.AddParameter(“query”, thepolice.ToJsonString());
request.RequestFormat = DataFormat.Json;
RestResponse response = client.Execute(request);
Console.WriteLine(“My output :” +”\n”+response.Content);

The output we get is as follows:


{“query”:{
“type”: “/music/artist”,
“name”: “The Police”,
“album”: null
}}
My output :
{
“code”: “/api/status/error”,
“messages”: [
{
“code”: “/api/status/error/mql/result”,
“info”: {
“count”: 31,
“result”: [
“Outlandos d’Amour”,“Reggatta de Blanc”,“Zenyatt\u00e0 Mondatta”,
“Ghost in the Machine”,“Synchronicity”,“Every Breath You Take: The Singles”,
“Greatest Hits”,“Message in a Box: The Complete Recordings”,
“Live!”,“Every Breath You Take: The Classics”,
“Their Greatest Hits”,“Can’t Stand Losing You”,
“Roxanne ‘97 (Puff Daddy remix)”,
“Roxanne ‘97”,“The Police”,“Greatest Hits”,
]
},
“message”: “Unique query may have at most one result. Got 31”,
“path”: “album”,
“query”: {
“album”: null,
“error_inside”: “album”,
“name”: “The Police”,
“type”: “/music/artist”}
}
],
“status”: “200 OK”,
“transaction_id”: “cache;cache04.p01.sjc1:8101;2011-09-06T20:48:46Z;0011”
}

Note carefully two things:-

1. The value of null instead of [] for album,this justifies the message we get in the output

2.If your query is wrong the status code will change to 400,here the code is 200 indicating the request is good.

Now let us try a quick fix of the problem

The method will be tweaked to make way for the [] instead of null to capture a set of albums instead of a single album.


public String ToJsonString()
{
return ”{“ +
JsonConvert.SerializeObject(“query”, Formatting.Indented) + ”:” +
”{“ + ”\n” +
JsonConvert.SerializeObject(“type”, Formatting.Indented) + ”:” +
JsonConvert.SerializeObject(this.type, Formatting.Indented) + ”,” + ”\n” +
JsonConvert.SerializeObject(“name”, Formatting.Indented) + ”:” +
JsonConvert.SerializeObject(this.name, Formatting.Indented) + ”,” + ”\n” +
JsonConvert.SerializeObject(“album”, Formatting.Indented) + ”:” +
”[]” + ”\n” + ”}” + ”\n” + ”}”;
}

The output is as follows:-


{“query”:{
“type”:”/music/artist”,
“name”:”The Police”,
“album”:[]}
}
My output :
{
“code”: “/api/status/ok”,
“result”: {
“album”: [
“Outlandos d’Amour”, “Reggatta de Blanc”,“Zenyatt\u00e0 Mondatta”,
“Ghost in the Machine”, “Synchronicity”,“Every Breath You Take: The Singles”,
“Greatest Hits”,“Message in a Box: The Complete Recordings”,
“Live!”,“Every Breath You Take: The Classics”,
“Their Greatest Hits”,“Can’t Stand Losing You”,
“Roxanne ‘97 (Puff Daddy remix)”,“Roxanne ‘97”,
“The Police”,“Greatest Hits”,
],
“name”: “The Police”,
“type”: “/music/artist”
},
“status”: “200 OK”,
“transaction_id”: “cache;cache04.p01.sjc1:8101;2011-09-06T21:02:11Z;0035”
}

Notice how everything becomes well and the error message goes away and the code in the first line changes from error to OK.

The next logical step would be to generate a helper method to give us a JsonString for all properties including lists,dictionary etc. I will try and address that in the next blog post.Hope this helps you start with Freebase.

I have omitted some set of results(not 31 if you count them :P) to keep it easy on the eye.