Skip to content
michael edited this page Sep 13, 2010 · 2 revisions

Please note: The project has recently been renamed to Ken. So all Mql occurances are out of date. To be updated soon…..

Welcome to the Mql wiki!

Introduction

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.

Example Usage

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


IMPORTANT

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.

Mql classes

The following object types are meant to encapsulate the corresponding Metaweb equivalents (again, I refer to the Mql Reference Guide)

Mql::Collection

Mql::Object

Mql::Type

Mql::Topic

Mql::Property

Mql::Namespace

Mql::Domain

Query API

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.

Write Syntax

And then?

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