LoginSignup
0
0

More than 5 years have passed since last update.

Ruby から MapR-DB JSON にアクセスしてみる

Last updated at Posted at 2017-12-01

「やりますか?どうしますか?とりあえずカレンダー作りますか?」っとか言いながら気づいたら12月になってしまいました。
MapRエンジニア勢が年末にかけて超絶忙しくなったため、もはやアドベントではなく正月の宿題、いや2018年中に終わればいいな(;´∀`)くらいになりそうですが、初日くらいは間に合わせたい!という気持ちで書いてみます。

ということで、MapR Advent Calendar 2017 の初日になります。

MapR-DB JSONとは

MapR-DBはMapR社が提供するNoSQLデータベースとなります。
MapR-DBはMapR-DB BinaryとMapR-DB JSONがあり、MapR-DB BinaryのほうはHBase APIを利用してアクセス出来ます。
MapR-DB JSONはMapR社がメインで開発しているOJAI(Open JSON Application Interface : オージェーエーアイ、オーハイと呼ばれることが多い)というAPIでアクセス出来ます。
両者の比較やMapR-DB BinaryとHBaseの比較については別の日にエントリーにしたいと思います。

今回はこちらの記事を参考にしながら、MapR-DB JSONにRubyからアクセスしてみます。

準備

Rubyからアクセスといっても、MapR-DB JSON用のバインディングはJava, C, Pythonしか提供されておらず、Rubyからアクセスしたい場合はJRubyを利用し、Javaのライブラリをインクルードする必要があります。
まずはご利用の環境でJRubyのインストールを行って下さい。

私の環境ではrvmをインストールしていたので、こちらで一発です。

# rvm install jruby
# rvm use jruby
# ruby -v
jruby 9.1.13.0 (2.3.3) 2017-09-06 8e1c115 OpenJDK 64-Bit Server VM 25.151-b12 on 1.8.0_151-b12 +jit [linux-x86_64]

Let's play

OJAIのAPIのドキュメントはこちらになります。
これを使って、まずはテーブルを作成し、データを突っ込んだり、編集したりしてみましょう。

include Java
Dir["/opt/mapr/lib/\*.jar"].each { |jar| require jar }

java_import com.mapr.db.MapRDB
java_import com.mapr.db.Table
java_import org.ojai.Document
java_import org.ojai.DocumentStream
java_import org.ojai.store.DocumentMutation
java_import org.ojai.store.QueryCondition
java_import org.ojai.store.exceptions.DocumentExistsException
java_import org.ojai.types.ODate

java_import java.io.IOException
java_import java.util.Arrays
java_import java.util.Iterator

java_import org.ojai.store.QueryCondition

tableName = "/user/mapr/db/testtable"
table = nil
if (!MapRDB.table_exists?(tableName))
  puts "Table Doesn't exist, creating"
  table = MapRDB.create_table(tableName)
else
  puts "Table exists"
  table = MapRDB.get_table(tableName)
end

これを実行するとパス /user/mapr/db/testdb にMapR-DB JSONテーブルが作成されます。

$ ruby test.rb
Table Doesn't exist, creating

$ maprcli table info -path /user/mapr/db/testtable -json
{
        "timestamp":1512113101782,
        "timeofday":"2017-12-01 02:25:01.782 GMT-0500",
        "status":"OK",
        "total":1,
        "data":[
                {
                        "path":"/user/mapr/db/testtable",
                        "numregions":1,
                        "totallogicalsize":0,
                        "totalphysicalsize":0,
                        "totalcopypendingsize":0,
                        "totalrows":0,
                        "totalnumberofspills":0,
                        "totalnumberofsegments":0,
                        "autosplit":true,
                        "bulkload":false,
                        "tabletype":"json",
                        "regionsizemb":4096,
                        "audit":false,
                        "maxvalueszinmemindex":100,
                        "adminaccessperm":"u:mapr",
                        "createrenamefamilyperm":"u:mapr",
                        "bulkloadperm":"u:mapr",
                        "indexperm":"u:mapr",
                        "packperm":"u:mapr",
                        "deletefamilyperm":"u:mapr",
                        "replperm":"u:mapr",
                        "splitmergeperm":"u:mapr",
                        "defaultcompressionperm":"u:mapr",
                        "defaultmemoryperm":"u:mapr",
                        "defaultreadperm":"u:mapr",
                        "defaulttraverseperm":"u:mapr",
                        "defaultwriteperm":"u:mapr",
                        "uuid":"fd99673e-4a43-1425-3851-0db603215a00"
                }
        ]
}

テーブルが出来ました。次に何かデータを入れて削除してみましょう
MapR-DB JSONではJSON型のドキュメントを作成し、このドキュメントをテーブルに登録します。
削除の際にはドキュメントやrowkeyを指定して削除するrowを選択出来ますが、ここではrowkeyを使ってみます。

# 上のコードに続けて

(10..20).each {|id|
  document = MapRDB.new_document
  .set("_id", "jdoe#{id}")
  .set("first_name", "John#{id}")
  .set("last_name", "Doe#{id}")
  .set("dob", ODate.parse("2016-06-23"))
  .set("drink", ["beer", "apple cider", "coffee"])
  .set("level", id)

  table.insert_or_replace(document)
}

# 検証
record = table.find_by_id("jdoe")
puts "jdoe's info #{record.inspect}"
record = table.find_by_id("jdoe15")
puts "jdoe15's info #{record.inspect}"
puts "jdoe15's drink info #{record["drink"]}"
table.delete("jdoe20")
record = table.find_by_id("jdoe20")
puts "jdoe20's info #{record.inspect}"

実行してみます。

$ ruby test.rb
Table exists
jdoe's info nil
jdoe15's info {"_id"=>"jdoe15", "dob"=>#<Java::OrgOjaiTypes::ODate:0x1e4d3ce5>, "drink"=>#<Java::ComMaprDbRowcol::DBList:0x4b5189ac>, "first_name"=>"John15", "last_name"=>"Doe15", "level"=>15}
jdoe15's drink info ["beer", "apple cider", "coffee"]
jdoe20's info nil

期待通り動いていますね。
おわかりのように格納するデータ型にはStringだけでなくさまざまな型が使えます。
ちなみにODateはOJAIで定義されているデータ型となります。

更新の際にもtableに対してreplace()やupdate()メソッドを利用することが出来ます。
ここではDocumentMutationクラスを利用した更新についてご紹介します。

DocumentMutationではドキュメントに対する更新をオブジェクトで持ち、これをテーブルのupdate()に渡してテーブルを更新することが出来ます。
この時、append() や merge()、increment()といったメソッドにより、型を意識した変更を表現することが出来ます。
試してみましょう。

# 上のコードに続けて

mutation = MapRDB.new_mutation

# 新規カラム追加
mutation.set("father's_name", "Andre")

# 既存カラムへの追記。同一のカラムに対しては最終の更新のみ反映
mutation.append("first_name", " Jonny")
mutation.append("first_name", " Jonathan")

# 既存のカラムでない場合は追加扱い
mutation.append("middle_name", "Smith")

# Array要素の追加
mutation.append("drink", ["fanta"])

# 削除
mutation.delete("last_name")

# Map型のマージ
mutation.merge("other_info", {"car" => "Mustang"})

# 数値のインクリメント
mutation.increment("level", 10)

table.update("jdoe15", mutation)
record = table.find_by_id("jdoe15")
puts record.inspect
puts record["drink"]

もはやRubyっぽさが全くないコードになってきましたが、気にしないでいきましょう。
実行してみます。

$ ruby test.rb
Table exists
jdoe's info nil
jdoe15's info {"_id"=>"jdoe15", "dob"=>#<Java::OrgOjaiTypes::ODate:0xa307a8c>, "drink"=>#<Java::ComMaprDbRowcol::DBList:0x6986852>, "first_name"=>"John15", "last_name"=>"Doe15", "level"=>15, "other_info"=>{"city"=>"LA"}}
jdoe15's drink info ["beer", "apple cider", "coffee"]
jdoe20's info nil
#<Java::ComMaprDbRowcol::MutationImpl:0x73a8da0f>
{"_id"=>"jdoe15", "dob"=>#<Java::OrgOjaiTypes::ODate:0x7d898981>, "drink"=>#<Java::ComMaprDbRowcol::DBList:0x21129f1f>, "father's_name"=>"Andre", "first_name"=>"John15 Jonathan", "level"=>25, "middle_name"=>"Smith", "other_info"=>{"car"=>"Mustang", "city"=>"LA"}}
["beer", "apple cider", "coffee", "fanta"]

期待通りですね。
遊び終わったらテーブルを掃除しておきましょう。

# 上のコードに続けて

MapRDB.deleteTable(tableName)

確認です。

$ ruby test.rb
...省略...
$ maprcli table info -path /user/mapr/db/testtable -json
{
        "timestamp":1512117965049,
        "timeofday":"2017-12-01 03:46:05.049 GMT-0500",
        "status":"ERROR",
        "errors":[
                {
                        "id":22,
                        "desc":"Requested file /user/mapr/db/testtable does not exist."
                }
        ]
}

掃除されていました。

さて、今回はRubyからMapR-DB JSONにアクセスしてみました。
次回はPythonからアクセスしてみる、予定です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0