つくりました。まだ完成してないけど。
タイトルには「DBI対応の」と断言していますが、テストはまだ通ってないのでDBIに完全に準拠してるのか、そもそもそれは可能なのか、わかりません。。が、もう実装するの疲れたのでフライングで紹介します。
インストール
install_github()
でインストールできます(CRANに上げるにはまだまだ時間かかりそう)
devtools::install_github("yutannihilation/Redashr")
使い方
Redashrのコネクションをつくるにはbase_url
、api_key
、data_source_name
を指定します。Redashに登録されているデータソースがひとつだけならdata_source_name
は省略可能です。
以下の例で使っているのは、PostgreSQLのデータベースを唯一のデータソースとするRedashです。警告は出ますがdata_source_name
は省略して問題ないです。
library(Redashr) redash_url <- "http://example.com/redash" api_key <- "xxxxxxxxxx" drv <- Redash() conn <- dbConnect(drv, base_url = redash_url, api_key = api_key) #> Warning: Using test as data source for now, but please provide #> data_source_name. #> Loading required package: RPostgreSQL #> Loading required package: DBI
Redashrは、データソースに合わせて必要なパッケージを読み込みます。ここではPostgreSQLにクエリを投げるためにRPostgreSQLパッケージが読み込まれています。(このパッケージはあらかじめインストールしておく必要があります)
ちなみに、PostgreSQL用のパッケージで言うとRPostgresパッケージの方がナウいんですけど、ちゃんとDBへの接続がないと使えないので諦めました。
ナウい方はクエリを組み立てるときにDBに依存しているらしく、単体では使えない。まあ正しい挙動ではある気がする。 pic.twitter.com/Wu0if5jP5n
— Hiroaki Yutani (@yutannihilation) 2017年10月13日
さて、DBIではコネクションに対してクエリを投げるための関数がいくつか用意されています。
dbSendQuery()
: 結果ではなくDBIResult
オブジェクトを返す。このオブジェクトをdbFetch()
すると結果が得られる。dbSendStatement()
: 結果は返ってこない。INSERT
とかUPDATE
とかデータ操作系のクエリを投げるときはこれ。dbGetQuery()
: 結果がdata.frameとして返ってくる。
すぐに結果が欲しいなら使いたいのはdbGetQuery()
でしょう。こんな感じです。
dbGetQuery(conn, "SELECT 1") #> # A tibble: 1 x 1 #> `?column?` #> <int> #> 1 1
dplyrから使う(まだ実装中)
まだ実装中なんですけど、簡単な例なら動きます。Rのdata.frameをcopy_to()
でコピーしてみましょう。
library(dplyr, warn.conflicts = FALSE) copy_to(conn, iris)
dbGetQuery()
でなにかクエリを投げてみるとちゃんとデータがコピーできていることがわかります。
dbGetQuery(conn, "SELECT COUNT(*) FROM iris;") #> # A tibble: 1 x 1 #> count #> <int> #> 1 150
dplyrではtbl()
を使うと、データベースのデータをdata.frameと同じように操作することができます。
redash_iris <- tbl(conn, "iris")
中身を覗いてみます。ちゃんとirisですね。(表示するだけでもデータベースへのアクセスが発生するので重いテーブルの場合は注意)。
redash_iris #> # Source: table<iris> [?? x 5] #> # Database: RedashConnection #> Sepal.Length Sepal.Width Petal.Length Petal.Width Species #> <dbl> <dbl> <dbl> <dbl> <chr> #> 1 5.1 3.5 1.4 0.2 setosa #> 2 4.9 3.0 1.4 0.2 setosa #> 3 4.7 3.2 1.3 0.2 setosa #> 4 4.6 3.1 1.5 0.2 setosa #> 5 5.0 3.6 1.4 0.2 setosa #> 6 5.4 3.9 1.7 0.4 setosa #> 7 4.6 3.4 1.4 0.3 setosa #> 8 5.0 3.4 1.5 0.2 setosa #> 9 4.4 2.9 1.4 0.2 setosa #> 10 4.9 3.1 1.5 0.1 setosa #> # ... with more rows
これを%>%
を使ってデータ操作していくことができます。
redash_iris %>% select(Sepal.Length, Sepal.Width, Species) %>% group_by(Species) %>% summarise(x = sum(Sepal.Length)) #> # Source: lazy query [?? x 2] #> # Database: RedashConnection #> Species x #> <chr> <dbl> #> 1 virginica 329.4 #> 2 setosa 250.3 #> 3 versicolor 296.8
ということで便利っぽいんですが、dplyrからちゃんと使えるようにするにはSQLの変換用メソッドを実装する必要があります。この辺がまだできていないので、まだ複雑なクエリだとうまく動きません。たぶん。
sql_render()
calls an SQL generation function (sql_select()
,sql_join()
,sql_subquery()
,sql_semijoin()
etc) to produce the actual SQL. Each of these functions is a generic, taking the connection as an argument, so that the details can be customised for different databases.
(https://cran.r-project.org/web/packages/dbplyr/vignettes/sql-translation.html)
Connections
RStudio Connectionsを読んで、とりあえず「New connection」のところにRedashが出てくるようにはしたんですけど、
新しくコネクションを開いたらタブに表示するようにする方(Connections Contract)はやることが多くてちょっとまだできていません。
TODO
- DBItestのテストを通す
- dplyrに対応する
- Connectionsタブに対応する
最後に
ということでできていないことだらけなんですけど、たぶん単純にdbGetQuery()
を使うだけなら問題なく使えると思います。Redashから結果を抜いてきてRに入れるのに苦労してという人は使ってみてください。
使ってて変なところを見つけたり要望を閃いたりすれば、Twitter、このブログのコメント欄、GitHubのissuesあたりでお知らせください。