F# Data: Freebase プロバイダー
Freebase グラフデータベース には 2,300万件以上の情報が格納されています。 この中からは書籍や映画、歴史的人物や出来事、化学元素など、 ありとあらゆる情報が互いに関連を持った形で見つけられます。
Freebase 型プロバイダーを使うと、こういった情報を手軽に取ってきて、 厳密に型付けされた状態でデータの山から宝物を見つけ出すことができます。
この型プロバイダーは Try F# の サイトにある「Data Science」のチュートリアルでも使われています。 そのためそちらも是非参考にしてみてください。 Visual Studio F#チームのブログではこの型プロバイダーについて 4つの記事が こちら に掲載されています。 また、Don Syme氏による動画デモが こちら で見られます。
プロバイダーの基本
以下のコードでは FSharp.Data.dll
ライブラリを(F# Interactive上で)読み込み、
GetDataContext
メソッドを使ってFreebaseへの接続を初期化しています:
1: 2: 3: 4: |
#r "../../../../bin/FSharp.Data.dll" open FSharp.Data let data = FreebaseData.GetDataContext() |
Freebaseデータの探索
さてこれで data.
と入力して表示される自動コンプリートの
リストをチェックするとFreebaseのデータスキーマを探索することができます。
たとえば以下のコードでは化学元素(Chemical Elements)のデータを取得して
水素(Hydrogen)の詳細情報を表示させています:
1: 2: 3: 4: 5: 6: 7: |
let elements = data.``Science and Technology``.Chemistry.``Chemical Elements`` let all = elements |> Seq.toList printfn "見つかった元素の数: %d" (Seq.length all) let hydrogen = elements.Individuals.Hydrogen printfn "原子番号: %A" hydrogen.``Atomic number`` |
テストケースの生成
Freebaseには非常に多様なデータがあるため、 ありとあらゆる用途にこのデータベースを利用できます。 以下のコードではデータベース上の婚姻データを使って それらしい名前をテスト用に生成しています。 まず2つの配列を用意します。 1つは(婚姻データを元にした)100件の名、そしてもう1つは (Freebaseに登録されている名字リストを元にした)100件の姓を含んでいます:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: |
let firstnames = data.Society.Celebrities.Celebrities |> Seq.truncate 100 |> Seq.map (fun celeb -> celeb.Name.Split([|' '|]).[0]) |> Array.ofSeq let surnames = data.Society.People.``Family names`` |> Seq.truncate 100 |> Seq.map (fun name -> name.Name) |> Array.ofSeq |
それらしいテストケース用のデータを生成するためには これらの配列からランダムに要素を抽出するヘルパ関数を用意して、 ランダム取り出した名と姓を連結します:
1: 2: 3: 4: 5: 6: 7: 8: 9: |
let randomElement = let random = new System.Random() fun (arr : string[]) -> arr.[random.Next(arr.Length)] for i in 0 .. 10 do let name = (randomElement firstnames) + " " + (randomElement surnames) printfn "%s" name |
Freebaseのデータにクエリを投げる
先ほどの例ではFreebase 型プロバイダーから返されたコレクションを処理するために
Seq
関数を使っていました。
単純な場合にはこれでいいのですが、そうではなくデータをフィルタしたり
クエリを投げたりする必要がある場合にはこのままではうまくいきません。
そこでFreebase プロバイダーにはクエリをサポートするための機能が用意されています。 F# 3.0のLINQシンタックスで記述されたクエリは (Freebaseで使われているクエリ言語である)MQLに変換されます。 これはつまりF# 3.0であれば自動補完のサポートも有効で、 厳密に型付けされた方法でクエリを作成できる上に、 少なくともMQLへと変換されたクエリはFreebaseのサーバー上で 効率的に処理されるというわけです。
以下では地球からの距離とあわせて恒星の名前を取得しています (距離が不定のデータは除きます):
1: 2: 3: 4: 5: 6: |
let astronomy = data.``Science and Technology``.Astronomy query { for e in astronomy.Stars do where e.Distance.HasValue select (e.Name, e.Distance) } |> Seq.toList |
例では簡単のために、まず恒星に関するデータを astronomy
という名前で定義しています。
また、クエリを実際に実行するために、最後に Seq.toList
を呼び出す必要もあります。
以下のクエリは距離が分かっていて、地球に近い恒星のデータを返します:
1: 2: 3: 4: |
query { for e in astronomy.Stars do where (e.Distance.Value < 4.011384e+18<_>) select e } |> Seq.toList |
クエリ言語では単純な where
や select
以外にも、
様々な演算子がサポートされています。
たとえば地球からの距離でソートした後、近い距離にある恒星を
上位10個取得することもできます:
1: 2: 3: 4: 5: |
query { for e in astronomy.Stars do sortBy e.Distance.Value take 10 select e } |> Seq.toList |
Freebase クエリ演算子
F# 3.0のクエリ演算子の他に、
FSharp.Data.FreebaseOperators
名前空間には
ApproximatelyMatches
ApproximatelyOneOf
ApproximateCount
Count
といったFreebase固有の演算子が定義されています。
これらはそれぞれ固有のMQL演算子に変換されます。
たとえば以下のコードでは Count
と ApproximateCount
を使って
歴代のアメリカ大統領の人数を数えています
(今回の場合、正確な人数を数えれば十分なので ApproximateCount
は
あまり有効ではありません):
1: 2: 3: 4: |
open FSharp.Data.FreebaseOperators data.Society.Government.``US Presidents``.Count() data.Society.Government.``US Presidents``.ApproximateCount() |
たとえば文字列を扱う場合には ApproximatelyMatches
を使うとよいでしょう。
以下では特定の文字列に およそ一致する 書籍を検索しています:
1: 2: 3: 4: 5: 6: 7: |
let topBooksWithNameContaining (s:string) = query { for book in data.``Arts and Entertainment``.Books.Books do where (book.Name.ApproximatelyMatches s) take 10 select book.Name } topBooksWithNameContaining "1984" |> Seq.toList |
プロバイダーの詳細機能
Freebase 型プロバイダーには非常に多くの機能があるため、 それらのすべてをここで紹介することはできません。 一部の機能については既に紹介しましたが、より詳しいドキュメントについては このページからリンクしてある記事を参照してください。 簡単に紹介すると以下のような機能があります:
- 多くのクエリは効率よくMQL言語へと変換されます。 これらはデフォルトではクライアントサイドでは実行できません。
- 特定のサンプルについては
Individuals
以下にあるオブジェクトの 各コレクションから取得できます。 この機能を使うとたとえばHydrogen
(水素)やBob Dylan
といった 厳密な名前をつかって特定のデータをプログラム上で取得することができます。 - Freebase上のデータに対して大まかな数を計算したり、 文字列を大まかに一致させるための独自の演算子がサポートされています。
- 画像のURLは
GetImages()
メソッドで取得できます。 また、1番目の画像はMainImage
プロパティで取得できます。 - Freebaseの日付によるスナップショットをサポートしています。 つまり特定の日付におけるFreebaseデータベースの状態を参照できます (また、スキーマが変更されない限りはアプリケーションが 壊れないということでもあります)。
- スキーマ情報をクライアントサイドでキャッシュするというオプションの機能を 使うことによって、型を迅速かつ効果的にチェックできます。
- 測定単位をサポートします。
たとえば化学元素の
Atomic mass
(原子質量)プロパティは自動的にSI単位である キログラムへと変換されます。 この情報は測定単位を使ってF#の型システム上で静的に伝搬されます。 - 大量のFreebaseデータに対してクエリを投げたい場合、 Googleで登録した後にカスタムAPIキーを取得します。 このキーは型プロバイダーのstatic引数で指定できます。
APIキーを指定する
FreebaseのAPIにはリクエスト数の制限があり、
当初はデバッグ用にある程度の割り当て分しか使うことが出来ません。
もしも(403) Forbiddenエラーが出たのであれば、それはつまり
リクエスト数の上限に達したということです。
Freebaseサービスを有効化するためにはAPIキーが必要です。
そうすれば1日あたり100,000件のリクエストを送信できるようになります。
F# Data ライブラリには FreebaseDataProvider
という型があり、
この型にはAPIキーなど、いくつかのstatic引数を指定することができます:
1: 2: 3: 4: 5: |
[<Literal>] let FreebaseApiKey = "<freebaseを有効にするgoogle API キーをここに入力>" //type FreebaseDataWithKey = FreebaseDataProvider<Key=FreebaseApiKey> //let dataWithKey = FreebaseDataWithKey.GetDataContext() |
MQLクエリのデバッグ
Freebase 型プロバイダーの仕組みを知りたい場合、
あるいはパフォーマンスの問題をデバッグしたい場合には
プロバイダーがFreebaseに送信するリクエストを確認するとよいでしょう。
そのためには SendingRequest
イベントに登録します:
1: 2: 3: 4: 5: |
data.DataContext.SendingRequest.Add (fun e -> printfn "request: %A" e.RequestUri) data.``Science and Technology``.Chemistry. ``Chemical Elements``.Individuals.Hydrogen.``Atomic mass``.Mass |
関連する記事
- Try F#: Data Science - Try F# の Data Science チュートリアルにはFreebase 型プロバイダーを使った 様々な例があります。
- Visual F# Team Blog: Integrating Internet-Scale Data Sources into a Strongly Typed Language - Freebase 型プロバイダーの基本に関する4つのシリーズ記事です
- Don Syme氏によるデモ - An Informal Deep Dive With Don Syme: The Freebase Type Provider
- API リファレンス: FreebaseDataProvider 型プロバイダー
- API リファレンス: FreebaseOperators モジュール
Full name: Freebase.data
static member GetDataContext : unit -> FreebaseService
nested type ServiceTypes
Full name: FSharp.Data.FreebaseData
<summary>Typed representation of Freebase data. See http://www.freebase.com for terms and conditions.</summary>
Full name: Freebase.elements
Full name: Freebase.all
from Microsoft.FSharp.Collections
Full name: Microsoft.FSharp.Collections.Seq.toList
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Full name: Microsoft.FSharp.Collections.Seq.length
Full name: Freebase.hydrogen
<summary>A sample set of named individuals (up to 1000 in size) of type 'Chemical Element' in the web data store</summary>
<summary>Hydrogen ( /ˈhaɪdrɵdʒɨn/ HY-drə-jin) is the chemical element with atomic number 1. It is represented by the symbol H. With an average atomic weight of 1.00794 u (1.007825 u for hydrogen-1), hydrogen is the lightest element and its monatomic form (H1) is the most abundant chemical substance, constituting roughly 75% of the Universe's baryonic mass. Non-remnant stars are mainly composed of hydrogen in its plasma state.
At standard temperature and pressure, hydrogen is a colorless, odorless, tasteless, non-toxic, nonmetallic, highly combustible diatomic gas with the molecular formula H2. Naturally-occurring atomic hydrogen is rare on Earth because hydrogen readily forms covalent compounds with most elements and is present in the water molecule and in most organic compounds. Hydrogen plays a particularly important role in acid-base chemistry with many reactions exchanging protons between soluble molecules.
In ionic compounds, it can take a negative charge (an anion known as a hydride and written as H), or as a positively charged species H. The latter cation is written as though composed of a bare proton, but in reality, hydrogen cations in ionic compounds always occur as more complex </summary>
Full name: Freebase.firstnames
<summary>Contains the objects of the domain category 'Society' defined in the web data store organized by type</summary>
<summary></summary>
<summary>A celebrity is a widely-recognized or famous person who commands a high degree of public and media attention. A celebrity is a widely-recognized or famous person who commands a high degree of public and media attention. Do not include non-celebrities in this type. </summary>
Full name: Microsoft.FSharp.Collections.Seq.truncate
Full name: Microsoft.FSharp.Collections.Seq.map
System.String.Split(separator: string [], options: System.StringSplitOptions) : string []
System.String.Split(separator: char [], options: System.StringSplitOptions) : string []
System.String.Split(separator: char [], count: int) : string []
System.String.Split(separator: string [], count: int, options: System.StringSplitOptions) : string []
System.String.Split(separator: char [], count: int, options: System.StringSplitOptions) : string []
from Microsoft.FSharp.Collections
Full name: Microsoft.FSharp.Collections.Array.ofSeq
Full name: Freebase.surnames
<summary> The people commons is a collection of common types that describe people in the system. The properties of person should be common across all people, i.e. birth date, birth place, relatives. People will often carry other types as well, such as author, basketball player, or recording artist. Properties that are particular to those pursuits should be included in those types, not in the person type. Similarly, it is recommend that 'birth date' and properties of the person schema not be replicated in other Types. Instead, 'person' should be an 'included type' for these types, which means that when a topic is typed 'author' it will also be automatically typed 'person' and the properties of person will be added as well. </summary>
Full name: Freebase.randomElement
type Random =
new : unit -> Random + 1 overload
member Next : unit -> int + 2 overloads
member NextBytes : buffer:byte[] -> unit
member NextDouble : unit -> float
Full name: System.Random
--------------------
System.Random() : unit
System.Random(Seed: int) : unit
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
System.Random.Next(maxValue: int) : int
System.Random.Next(minValue: int, maxValue: int) : int
Full name: Freebase.astronomy
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
<summary>A star is really meant to be a single stellar object, not just something that looks like a star from earth. However, in many cases, other objects, such as multi-star systems, were originally thought to be stars. Because people have historically believed these to be stars, they are type as such, but they are also typed as what we now know them to be. </summary>
Calls Linq.QueryBuilder.Where
<summary>The best approximated measurement from the earth to the object in parsecs.</summary>
Calls Linq.QueryBuilder.Select
Calls Linq.QueryBuilder.SortBy
Calls Linq.QueryBuilder.Take
from FSharp.Data
<summary>The government domain is for all things related to the people and institutions that make up a government. It includes political parties, politicians, elections, government offices, electoral districts, etc., and covers all levels of government, from local to national.The types in this domain have been designed so that they can be used for all types of government, including (but not limited to) US-style federal republics, Westminster-style parliamentary systems, Chinese-style communist governments, and monarchies. Please let us know if you come across a system that doesn't seem to fit the model, so that we can try to accomodate it.For information about entering data for politicians, elected officials, and other public servants, see Entering information about electioned officials and public servants. The government domain is for all things related to the people and institutions that make up a government. It includes political parties, politicians, elections, government offices, electoral districts, etc., and covers all levels of government, from local to national.The types in this domain have been designed so that they can be used for all types of government, including (but not limited to) US-style federal republics, Westminster-style parliamentary systems, Chinese-style communist governments, and monarchies. Please let us know if you come across a system that doesn't seem to fit the model, so that we can try to accomodate it.For information about entering data for politicians, elected officials, and other public servants, see Entering information about elected officials and public servants. </summary>
Full name: Freebase.topBooksWithNameContaining
type LiteralAttribute =
inherit Attribute
new : unit -> LiteralAttribute
Full name: Microsoft.FSharp.Core.LiteralAttribute
--------------------
new : unit -> LiteralAttribute
Full name: Freebase.FreebaseApiKey