-
Notifications
You must be signed in to change notification settings - Fork 18
Home
Please note: The project has recently been renamed to Ken. So all Mql occurances are out of date. To be updated soon…..
The Mql-Library will be built to access the Metweb Services supplied by freebase.com.
Just born, the project’s goals are the provision of a concise API for querying and writing. Therefore I think the use of easy to understand mappings to Ruby Objects (which represent the Metaweb Architecture) is crucial for such an interface.
If things go right, you should be able to use this library as a data layer (instead of or in addition to ActiveRecord/DataMapper) for your web framework of choice (Merb, Rails).
The Freebase Database can be thought of as a huge graph of interconnected nodes that represent knowledge (in a much more structured way than wikipedia does). That graph can be viewed at a higher level through an object-oriented lens which leads to easier interaction.
To understand the fundamental Metaweb Architecture please read the official MQL Reference guide (with focus on Chapter 2) provided by Freebase.
This section should serve as an API Design playground, where ideas are just written down.
At first, for the sake of easiness, I will not take care of ruby syntax quirks (reserved variable/constant names etc.)
The whole Library will be built around the Mql Module (the name of the whole library, and hence the name of the module, might change in the future ;-) )
# Mql.select returns a Mql::Collection object, which proxies an array of Mql::Topic objects which derives from Mql::Object
artists = Mql.select(:type => "/music/artist", :genre => "/en/rock_music", :limit => 10)
artists.each do |artist|
artist.id # => e.g. /en/the_rolling_stones
artist.name # => e.g. The Rolling Stones
artist.types # => an array of assigned types for that object encapsulated in an Mql::Type object
# I could think of a lazy loading pattern for properties at a deeper level (to load them on demand) / not sure what makes sense here
artist.albums.each do |album|
# a property can either be a value or a link to another object
# the album(s) property refers to a another object of type "/music/album" which has again.. properties
album.id
album.name
album.tracks => Mql::Collection, which again contains Mql::Topic objects
# and so forth ;)
end
# as well you can iterate over all properties by simply calling
artist.properties.each |property|
property # => returns either the value in case of an value type or another object it refers to
# value types should map to the suitable Ruby type
# object types are again Mql::Topic objects
# in case it's a non-unique object type property a Mql::Collection is returned in
# in case of multi-valued value types a simple ruby array would do the trick?!
end
end
Do not consider the code listed above to be a correct representation of the Metaweb Architecture.. I’m just playing around… It should just give you a feeling in which direction it should go.
There’s one important goal I want to accomplish. That is viewing each row of an MQL-Query result as a (lets say…) generic Resource (or Node) Object. That Resource represents an Entity in the graph (identified by the id of that Node). You would then have instant access to all properties that are returned by the MQL Response as a result of the specified Query.
Let’s look at an example:
Let’s say you specify a query that fetches an MQL Node by id and also name some properties you want to have returned in the result
Keep in mind that you can’t use shorhand syntax for properties such as active_start, active_end if you do not specify a type property explicitly.
Instead you must name the complete property identifier that is e.g. /music/artist/active_start
I don’t care about that for that example because a syntax like :“/music/artist/active_start” looks strange to me ;)
the_police = Mql.first(:id => "/en/the_police", :origin => nil, :name => nil, :active_start => nil, :active_end => nil)
the_police.name # => "The Police"
the_police.active_start # => 1977-01
the_police.active_end # => 1986
You should than have instant access to that explicitly denoted properties.
But what if you want to list ALL outgoing properties from /en/the_police?
Since Freetype objects consists of several types and each type defines it’s set of properties we have to ask each type for it’s properties
Sadly, we need more queries to accomplish this.
First we need to fetch the set of types and their corresponding properties
Accessing the_police.types would lead to an Mql query looking just like this:
{
"id" : "/music/artist",
"properties" : [{
"id": null,
"expected_type" : null
}],
"type" : "/type/type"
}
It could be implemented like so that the_police.types returns a collection of types encapsulated in a Mql::Type ruby object
# We can inspect that types like so
the_police.types.each do |type|
type.id # => e.g. /music/artist
type.properties => # a collection of Mql::Property objects
type.properties.each do |property|
property.id # => e.g. /music/artist/home_page
property.expected_type # => e.g. /common/webpage
end
end
We now know what properties we have (based on the Freebase object’s types)
But things are getting a bit complicated now. How does this help? What next?
We just want to access the_police.webpage. Don’t we?
I could just think of a solution like this:
Of course we need another query….
We could define a method_missing method in our Mql::Resource class, which the_police is an instance of.
As soon as an unknown property is accessed we first trigger the loading of that types needed (as shown above)
Then I would propose to execute a query that fetches all the properties (which can be derived from the types array) in one go.
I didn’t find out how to formulate an MQL query which does exactly this. However we can also use multiple queries packed in a query envelope to accomplish this.
Things get even more complicated when we have to deal with properties that refer to object types (especially multi-valued ones).
But I’m sure with a smart implementation all that can be solved efficiently.
I’m aware of the fact that queries that supply a type attribute are much faster and easier to handle.
But that assumes that you already know what you want to query, not giving you the possibility to inspect a Resource (or Node) as a whole.
The following object types are meant to encapsulate the corresponding Metaweb equivalents (again, I refer to the Mql Reference Guide)
I thought about implementing an Ambition Adapter.
Because of the Hash-oriented nature of the MQL Query syntax i’m not quite sure if that would be the way to go.
Anyway.. I really like Ambition’s operator overloads ;)
For the moment, and for first testing purposes later-on, the hash based syntax (as shown in the example) should be enough.
If you discovered inconsistencies in this (little ;) ) rant, have suggestions or want to contribute please let me know.
I would be glad to get some help from you.
Thanks,
Michael