読者です 読者をやめる 読者になる 読者になる

Rからパラメータ付きCypherクエリを投げる

R Neo4j

KaggleやCrowdSolvingでレコメンのコンペが開催されたときに使いたいなぁと思ってNeo4jの勉強を始めたのですが、グラフDBに適した問題がなかなか出てきません。 今回はNeo4j 2.0がリリースされた記念に記事を書いてみました。

目標

RからCypherクエリを投げて結果をデータセットにします。 いついかなる時もCypherクエリはパラメータ化すべきとのことなので、それにも従います。

使用データ

KaggleのEvent Recommendation Engine Challengeデータを使っています。 BatchInserterを使ってDBに挿入したのですが、重複レコードがたくさんあって大変でした。

CSVファイルの容量は1.5GBくらいですが、Neo4jに放り込むと5.5GBくらいになりました。

参考

Stack Overflowにあったコードをベースにしています。 こういうのも見つけましたが、ざっと眺めた感じパラメータ化はされていないようです。

コード

library(RCurl)
library(RJSONIO)
getQuery <- function (query, params) {
  h  =  basicTextGatherer()
  pf <- toJSON(list(query=query, params=params))
  curlPerform(url="localhost:7474/db/data/cypher",
              httpheader=c("Content-Type"="application/json"),
              customrequest="POST",
              postfields=pf,
              writefunction=h$update)
  result <- fromJSON(h$value())
  if (is.element("exception", names(result))) {
    dat <- result
  } else {
    dat <- data.frame(t(sapply(result$data, function(y) y)))
    if (ncol(dat)==length(result$columns)) {
      names(dat) <- result$columns
    }
  }
  return(dat)
}

参考にしたコードと異なり、クエリとパラメータをJSON形式で渡すので、httpheaderでそれを設定しています。

実行

あるイベントについて、指定したユーザの友人の内から何名がそれに参加しているかを問い合わせます。

query <-
"START u = node:users(user_id = {uid})
MATCH u-[:FOLLOW]->f-[:ATTEND]->e
RETURN u.user_id, e.event_id, count(e) LIMIT 10"
dat      <- NULL
params   <- list(uid="3197468391")
dat[[1]] <- getQuery(query, params))
params   <- list(uid="3429017717")
dat[[2]] <- getQuery(query, params))

実行すると、

[[1]]
    u.user_id e.event_id count(e)
1  3197468391  169644382        1
2  3197468391  543972501        1
3  3197468391 3969940212        1
4  3197468391 2977769484        1
5  3197468391 1704179171        1
6  3197468391  608092517        3
7  3197468391  730958187        1
8  3197468391   19341280        1
9  3197468391  445373500        1
10 3197468391 2539029764      284

[[2]]
    u.user_id e.event_id count(e)
1  3429017717 3183605169        2
2  3429017717 2180806657       46
3  3429017717 2039358442        2
4  3429017717 2412032092        2
5  3429017717 3541811987        1
6  3429017717 2368083210        1
7  3429017717 1506378274        1
8  3429017717 1177314523        1
9  3429017717 3163090701       12
10 3429017717  266513530        1

ちゃんと結果が返ってきました。僅かですがベタ書きより良いパフォーマンスも確認できました。めでたしめでたし。