Tuesday, December 27, 2011

Neo4j 使い方メモ

今、Neo4jを調査しているのでメモ。

Neo4jはグラフDBとよばれるNoSQL系のデータベースです。Twitterのフォロー関係のような、有向グラフ構造を保存できます。

http://neo4j.org/

Neo4jはJavaからは組み込みで利用できますが、その他ネイティブ系のバインディングが全然ありません。そのかわり、RESTによるJSON/HTTPのインターフェイスが用意されています。

ここではRESTサーバーとRubyクライアントのセットでNeo4jを利用する例を紹介します。

サーバーのインストール

Neo4jサーバーをコマンドラインから起動するだけなら、ダウンロードページから落としてきて起動するだけ。

サービスに登録するためのコマンドも用意されています。

sudo ./bin/neo4j install

サーバー起動

$ cd NEO4J_HOME
$ bin/neo4j start

以下のURLからWebの管理画面を表示できます。

http://localhost:7474/webadmin

サーバー終了

$ bin/neo4j stop

データの削除

以下のフォルダを削除すると、全てのデータを消去できます。

NEO4J_HOME/data/graph.db
ただし、サーバーが停止しているときに消さないといけないみたいです。消したつもりが復活したりしました。

データ削除インターフェイスを追加するアドオンとかも見つけましたが、1.5までの対応のようです。(執筆時点でのNeo4j最新は1.6。無理矢理動くかは未検証)

https://github.com/jexp/neo4j-clean-remote-db-addon

ドキュメント

RESTインターフェイスについては以下にドキュメントがあります。

http://docs.neo4j.org/chunked/milestone/rest-api.html

ただ、そこまで充実しているわけではありません。 Java APIも含め、全体を網羅したPDFもありました。

http://docs.neo4j.org/pdf/neo4j-manual-stable.pdf

Neography

僕はRubyから利用したいので、NeographyというNeo4jのRESTクライアントを使います。

https://github.com/maxdemarzi/neography

インストールはgemで。

gem install neography

Neography以外にも、RailsのActiveModelのように動作するものとして、以下のようなものがあるようです。

  • neology: Neographyのラッパー
  • architect4r: よりActiveModelに近いが、クエリーのみ実装されていて、index等はサポートしない

traverse

ノードやリレーションの作成などのシンプルな操作はgithubのサンプルを見てもらうとして、グラフをトラバースする方法についてメモしておきます。ちょうどneographyを使ったfacebookの友達サジェストのサンプルがありました。

https://github.com/maxdemarzi/neography/blob/master/examples/facebook.rb

サジェストする部分を見てみます。

def suggestions_for(node)
  @neo.traverse(node, "nodes", {
    "order"         => "breadth first",
    "uniqueness"    => "node global",
    "relationships" => { "type" => "friends", "direction" => "in" },
    "depth"         => 2,
    "return filter" => {
      "language" => "javascript",
      "body"     => "position.length() == 2;"
    }
  }) 
end

最初の引数nodeはグラフ走査の起点です。第二引数"nodes"はノードの走査をする、ということを指定しています。 第三引数のオプションとして、それなりの指定があります。

orderでは幅優先"breadth first"を指定しています。他に深さ優先"depth first"が指定できます。

return filterでは、検索条件を指定します。ここではnodeから2ホップのノード(友達の友達)を返すように指定しています。

depthでは、トラバースする際の最大の深度を指定しています。

Cypher

Neo4j特有のクエリー言語として、Cypherがあります。

http://docs.neo4j.org/chunked/snapshot/cypher-query-lang.html

neo.execute_queryというメソッドでCypherクエリーを実行できます。 たとえば先ほどの友達サジェストは、以下のように書けます。

require 'rubygems'
require 'neography'

@neo = Neography::Rest.new

def create_person(name)
  @neo.create_node("name" => name)
end

def make_mutual_friends(node1, node2)
  @neo.create_relationship("friends", node1, node2)
  @neo.create_relationship("friends", node2, node1)
end

def suggestions_for(node)
  n = Neography::Node.new node
  q = "START n=node(#{n.neo_id}) MATCH n -[:friends]-> f -[:friends]-> t WHERE not(t.name = n.name) RETURN t.name"
  result = @neo.execute_query(q)
  result["data"].map { |f| f.first }
end

johnathan = create_person('Johnathan')
mark      = create_person('Mark')
phill     = create_person('Phill')
mary      = create_person('Mary')
luke      = create_person('Luke')

make_mutual_friends(johnathan, mark)
make_mutual_friends(mark, mary)
make_mutual_friends(mark, phill)
make_mutual_friends(phill, mary)
make_mutual_friends(phill, luke)

puts "Johnathan should become friends with #{suggestions_for(johnathan).join(', ')}"
結果:
Johnathan should become friends with Mary, Phill

ここで実行しているクエリーはこんな感じです。

START n=node(#{n.neo_id})
MATCH n -[:friends]-> f -[:friends]-> t
WHERE not(t.name = n.name)
RETURN t.name

traverseの例とちょっと論理的に同等とは言えないかもしれませんが(同値チェックのあたり)、この例ではうまく動きます。 Cypherではこのように、STARTで起点、MATCHで検索条件、WHEREでフィルター条件、RETURNで戻り値を記述します。MATCHの記法はなかなか強力で、a -[:link]-> t <-[:link]- bのように、逆向きのリレーションも扱えます。

その他

TinkerPopというところが、グラフDBのためのソフトウェアスタックを用意しています。

http://tinkerpop.com/

グラフのトラバースなどに特化したクエリー言語Gremlinや、RESTインターフェイスのRexsterなどがあります。 本当ならNeo4jを直に使うよりこちらを経由した方が良いと思うのですが、ちょっとまだこなれてない感じがしました。

今日のところは、とりえあえずここまで。

Monday, October 10, 2011

jQuery+jsonpでエラーハンドリング

jQueryの$.ajaxでjsonpを使うと、errorハンドラが発火しない。jQuery+jsonpでエラーハンドリングが必要なケースは、jquery-jsonpを使う。

$.jsonp({
  url: url,
  dataType: 'jsonp',
  callbackParameter: 'callback', // パラメータ名がjsonpではなくcallbackParameter
  success: function(data, status) {},
  error: function(XHR, textStatus, errorThrown){}
});

参考:jQuery ajax (jsonp) ignores a timeout and doesn't fire the error event

Thursday, September 15, 2011

Cameleon : HTTPスタブ フレームワーク

Rubyで書かれたHTTPのダミー/モックサーバーを手軽に作るためのツール、Cameleonをリリースしました。

仕事でよくHTTPの外部システムを使うアプリを作ることがあるのですが、Cameleonはその外部システムのモックを簡単に作るために開発しました。何度か実際の開発案件で利用しています。

使い方はRuby on Railsの感じを参考にしています。

特徴

  • 基本はレスポンスのファイルをフォルダに配置するだけ
  • "_switch.rb"というシンプルなRubyのDSLでレスポンス用のファイルを選択
  • RESTfulなサービスのモックも簡単に作成できる(HTTPメソッドサポート)

インストール

Rubygemsで一発インストール

$ gem install cameleon
インストールできるとcameleonコマンドが使えるようになります。

Getting started

まずは、cameleonのプロジェクトをnewコマンドで作ります。

$ cameleon new your_project_name
できたディレクトリに移動してserverコマンドを実行するとデフォルトでポート9292でサーバーが起動します。
$ cd your_project_name
$ cameleon server
別のターミナルを立ち上げて、curlでテストしてみましょう。
$ curl http://localhost:9292
Hey, I am cameleon!
Edit response folder to change response whatever you want.
see README.md more detail.
はい、とりあえず動いていることは確認できました。

使い方

たとえば次のようなインターフェイスを作成することを考えます。

  • URLのパスが/path/to/interface
  • レスポンスは単純に"ok"
この場合、cameleonではresponse/path/to/interfaceディレクトリを作成し、その中にokと書いたファイルをdefault.txtとして保存すればOKです。
$ mkdir -p response/path/to/interface
$ cd response/path/to/interface
$ echo "ok" > default.txt
curlでテストしてみましょう。
$ curl http://localhost:9292/path/to/interface
ok
同様のことはgenerateコマンドを使うとより簡単です。ここでは/path/to/fooに新しいインターフェイスを作ってみます。
$ cameleon generate path/to/foo
こちらもテスト。
$ curl http://localhost:9292/path/to/foo
edit me: response/path/to/foo/default
作成できてますね。レスポンスは必要な内容に書き換えて下さい。

_switch.rb

普通アプリ開発で利用するのであれば、モックとはいえ、レスポンスをリクエストに応じて変化させる必要があるでしょう。そのときはフォルダ内に"_switch.rb"というファイルを作成し、その中でどのレスポンスファイルをレンダリングするかを選択します。

_switch.rbはRubyで自由に記述できます。レスポンスの内容を切り替えるためには、renderメソッドでレスポンスファイルを選択します。renderメソッドが呼ばれると、そこで_switch.rbからはすぐに抜け、以降の処理は継続しません。逆に、最後までrenderメソッドが呼ばれなかった場合は、defaultで始まるファイルをレンダリングします。また、_switch.rbではparamsにリクエストパラメータが格納されているので、これを使ってレスポンスを選択するといいでしょう。

_switch.rbのサンプルです。

# you can access URL parameters by 'params'
case params[:key]
when "foo"
  # curl http://localhost:9292/gallery/params?key=foo
  render "foo.txt"
when "bar"
  # You can also use POST or PUT. See 'rest' more about hadling HTTP methods.
  # curl -XPOST http://localhost:9292/gallery/params -d"key=bar"
  render "bar.txt"
end

# if else, render "default" (any extention acceptable) file.

Gallery

galleryコマンドで、response/galleryディレクトリにサンプルが出力されます。最初は_switch.rbで使えるAPIなどの参考になるとおもいますので利用して下さい。

$ cd YOUR_CAMELEON_HOME
$ cameleon gallery

私はけっこう便利に使えているので、ぜひ利用してみて下さい。

Wednesday, August 31, 2011

markd

markd is rich html builder for markdown, and is especially focused on printing purpose. You can get well-formatted printings (or PDF by preview) when you print html using modern browser (such as Google Chrome, Firefox, Safari).

Source code is available on github.

markd is based on bluecloth and google code prittify.

features:

  • Well-formatted HTML with CSS
  • Good style for printings
  • Auto numbered chapters
  • Code Highlighting

Installation

You can install markd using RubyGems as below:

$ gem install markd

Usage

Build html from markdown:

$ markd -o out_dir markdown.md
where markdown.md is target markdown file and out_dir is directory that html/css/js files are generated into.

Use -h (or --help) option to show detail.
$ markd -h

License

markd is released under the MIT license.

Enjoy!

Monday, August 29, 2011

Facebookのユーザーのサムネイル

Facebook からユーザーのサムネイル画像を取得するのは次のURL。
<img src="http://graph.facebook.com//picture?type=square" />
UserIDを取得するのは、facebook_oauthでは
client = FacebookOAuth::Client.new(
  :application_id     => "your application id",
  :application_secret => "your application secret",
  :token              => "your token"
)
user_id = client.me.info["id"]

Thursday, August 25, 2011

markd

markdを公開しました。Rubyで書かれたMarkdownをHTMLに変換するツールです。特にソースコードを含むドキュメントを簡単かつ奇麗に作成することができます。ソースはgithubから。

念のため説明すると、markdownはeメールの装飾でよく使われる書式でテキストファイルをマークアップするフォーマットです。 githubに登録されているプロジェクトの多くのトップでREADME.mdが表示されいますが、これがmarkdownです。markdown記法についてはこちらのページが詳しいです。

markdはそのmarkdown形式のファイルからHTMLファイルを出力するコマンドラインツールです。markdの出力はHTMLですが、ブラウザから印刷することでそれなりの品質のドキュメントとなることを目指しています。

markdの特徴
  • ソースコードがカラーリングされる
  • h1, h2タグに章番号が自動で振られる
  • ブラウザからの印刷に最適化されている
RubyのMarkdownプロセッサには既にblueclothなどがあります。markdも内部でblueclothを利用しています。 markdはblueclothの出力結果に対してHTMLを整形し、CSS/Javascriptを追加してデフォルトで一通りレイアウトされた結果を出力します。

インストール

Rubygemsでインストールできます。
$ gem install markd

使い方

markdコマンドに引数でmarkdownファイルを渡します。
$ markd markdown.md
デフォルトではdocsというディレクトリが作成され、その中にHTMLファイルなどが生成されます。出力先を変更したい時には-oオプションを使います。
$ markd -o OUTPUT_DIR markdown.md
この例ではOUPUT_DIRというディレクトリに結果が出力されます。

ライセンス

MITライセンスです。

Tuesday, April 12, 2011

gitで任意のファイルを、特定のリビジョンとGUIで比較(mac)

gitで任意のファイルを、特定のリビジョンとGUIで比較したい。Macの場合、GitXだとできないっぽい。 そこで、XCodeと一緒に入るFileMergeを使って差分をみる。
$ git difftool -t opendiff -y {revision} -- {path/to/file}