前回はMongoDB Shellからでしたが、今度はJava系の言語からMongoDBを扱ってみたいと思います。
今回行うのは、前回の縮小版です。
http://d.hatena.ne.jp/Kazuhira/20130613/1371127093
はい。
で、対象はJava、Groovy、Scalaで。それではいってみましょう。
*Clojure版も書きました
http://d.hatena.ne.jp/Kazuhira/20130901/1378019591
Java
Javaは、オフィシャルなドライバが提供されています。今回使ったバージョンは、2.11.1ですね。
Java Driver
http://docs.mongodb.org/ecosystem/drivers/java/
Getting Started with Java Driver
http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-java-driver/#getting-started-with-java-driver
API Documentation
http://api.mongodb.org/java/2.11.1/
基本的には、Getting Startedを見ていきつつ、ちょっと困ったらAPI Documentを見る感じで。
ビルドはGradleでやりました。
build.gradle
apply plugin: 'java' apply plugin: 'application' mainClassName = 'MongoDBClientSample' repositories { mavenCentral() } dependencies { compile 'org.mongodb:mongo-java-driver:2.11.1' }
作成したコード。
src/main/java/MongoDBClientSample.java
import java.net.UnknownHostException; import java.util.Arrays; import java.util.ArrayList; import java.util.List; import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.WriteConcern; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.DBCursor; public class MongoDBClientSample { public static void main(String[] args) { MongoClient mongoClient = null; try { // MongoDBに接続 mongoClient = new MongoClient("localhost", 27017); // ローカルで動かすなら、以下でもOK // mongoClient = new MongoClient(); // レプリカセットに接続する時は、ServerAddressを使うらしい… // 使用するデータベース DB db = mongoClient.getDB("tutorial"); // コレクション名を「nosql」にします DBCollection nosql = db.getCollection("nosql"); // データの登録 // 1件ずつ nosql.insert(new BasicDBObject("name", "MongoDB") .append("type", "Document Database")); nosql.insert(new BasicDBObject("name", "CouchDB") .append("type", "Document Database")); nosql.insert(new BasicDBObject("name", "Memcached") .append("type", "Key Value Store")); // 複数件 List<DBObject> documents = new ArrayList<>(); documents.add(new BasicDBObject("name", "Apache Cassandra") .append("type", "Column Database")); documents.add(new BasicDBObject("name", "Apache HBase") .append("type", "Column Database")); nosql.insert(documents); // 検索 // find for (DBObject dbObject : nosql.find()) { System.out.println("find => " + dbObject); } for (DBObject dbObject : nosql.find(new BasicDBObject("type", "Column Database"))) { System.out.println("find(condition) => " + dbObject); } // findOne System.out.println("findOne => " + nosql.findOne()); System.out.println("findOne => " + nosql.findOne(new BasicDBObject("name", "Apache Cassandra"))); // 件数 System.out.println("count => " + nosql.count()); System.out.println("count(condition) => " + nosql.count(new BasicDBObject("name", "Apache Cassandra") .append("type", "Column Database"))); // 更新 // $set nosql.update(new BasicDBObject("name", "MongoDB"), new BasicDBObject("$set", new BasicDBObject("url", "http://www.mongodb.org/"))); nosql.update(new BasicDBObject("name", "Memcached"), new BasicDBObject("$unset", new BasicDBObject("type", 1))); // save nosql.save(new BasicDBObject("name", "Redis").append("type", "Key Value Store")); BasicDBObject redis = (BasicDBObject) nosql.findOne(new BasicDBObject("name", "Redis")); redis.append("url", "http://redis.io/"); nosql.save(redis); // ドキュメントの削除 nosql.remove(new BasicDBObject("name", "Apache HBase")); for (DBObject dbObject : nosql.find()) { System.out.println(dbObject); } // コレクションの全データを削除 nosql.remove(new BasicDBObject()); } catch (UnknownHostException e) { e.printStackTrace(); } finally { mongoClient.close(); } } }
基本的な意味はコメントに書いていますが、だいたいBasicDBObjectみたいなJSONライクなクラスを使いつつ、コレクションに対して操作していく感じみたいです。
かなり、面倒でした…。
Groovy
実は、最初にやったのはこちらです。いわゆるLLですしね、MongoDBとはGroovyの方がきっと相性が良いでしょう。
といっても、Groovyはオフィシャルなドライバは存在しません。サードパーティ製のGMongoというドライバがあります。
GMongo
https://github.com/poiati/gmongo
ちょっと使ってみると分かるのですが、これはJava Driverのラッパーな感じです。よって、Java DriverのAPI Documentとかもけっこう見ることになります。
それでは、作成したコードを。依存関係の解決には、Grapeを使用しています。
getting_started.groovy
@Grab('com.gmongo:gmongo:1.0') import com.gmongo.GMongo // MongoDBに接続 def mongo = new GMongo('localhost', 27017) // ローカルで動かすなら、以下でもOK // def mongo = new GMongo() // 使用するデータベース def db = mongo.getDB('tutorial') // コレクション名を「nosql」にします // データの登録 // 1件ずつ db.nosql.insert([name: 'MongoDB', type: 'Document Database']) db.nosql.insert(name: 'CouchDB', type: 'Document Database') db.nosql << [name: 'Memcached', type: 'Key Value Store'] // 複数件 db.nosql << [ [name: 'Apache Cassandra', type: 'Column Database'], [name: 'Apache HBase', type: 'Column Database'] ] // 検索 // find db.nosql.find().each { println("find => $it") } db.nosql.find(type: 'Column Database').each { println("find(condition) => $it") } // findOne println('findOne => ' + db.nosql.findOne()) println('findOne(condition) => ' + db.nosql.findOne(name: 'Apache Cassandra')) // 件数 println('count => ' + db.nosql.count()) println('count(condition) => ' + db.nosql.count(name: 'Apache Cassandra', type: 'Column Database')) // 更新 // $set db.nosql.update([name: 'MongoDB'], [$set: [url: 'http://www.mongodb.org/']]) // $unset db.nosql.update([name: 'Memcached'], [$unset: [type: 1]]) // save db.nosql.save(name: 'Redis', type: 'Key Value Store') db.nosql.findOne(name: 'Redis').with { db.nosql.save(it << [url: 'http://redis.io/']) } // ドキュメントの削除 db.nosql.remove(name: 'Apache HBase') db.nosql.find().each { println(it) } // コレクションの全データを削除 db.nosql.remove([:]) // 接続終了 mongo.close()
やっぱり、Groovyが1番簡単でした。Mapとかキーワード引数で簡単に操作できるのは、便利ですね。
Scala
Scalaの場合も、オフィシャルなドライバが存在します。Casbahという名前らしいです。
Casbah
http://mongodb.github.io/casbah/index.html
Tutorial: Using Casbah
http://mongodb.github.io/casbah/tutorial.html
API Documentation
http://mongodb.github.io/casbah/api/#com.mongodb.casbah.package
あと、こちらのサイトも参考にさせていただきました。
http://blog.restartr.com/2011/03/07/access-to-mongodb-in-scala-with-casbah/
今回使用したCasbahのバージョンは2.6.1ですが、Mavenリポジトリを見てると3.0.0が開発中のようですね。
ビルドには、sbtを使いました。
build.sbt
name := "mongodb-client-sample" version := "0.0.1-SNAPSHOT" scalaVersion := "2.10.2" organization := "littlewings" libraryDependencies += "org.mongodb" %% "casbah" % "2.6.1"
作成したコード。
src/main/scala/MongoDBClientSample.scala
import com.mongodb.casbah.Imports._ object MongoDBClientSample { def main(args: Array[String]): Unit = { // MongoDBに接続 def mongo = MongoClient("localhost", 27017) // ローカルで動かすなら、以下でもOK // def mongo = MongoClient() try { // 使用するデータベース val db = mongo("tutorial") // コレクション名を「nosql」にします val nosql = db("nosql") // データの登録 // 1件ずつ nosql.insert(MongoDBObject("name" -> "MongoDB", "type" -> "Document Database")) // += メソッドでもOK nosql += MongoDBObject("name" -> "CouchDB", "type" -> "Document Database") // 実は、Mapでもinsertできます… /* nosql += Map("name" -> "CouchDB", "type" -> "Document Database") */ // Builderを使用 val memcachedBuilder = MongoDBObject.newBuilder memcachedBuilder += "name" -> "Memcached" memcachedBuilder += "type" -> "Key Value Store" nosql += memcachedBuilder.result // 複数件 nosql.insert(MongoDBObject("name" -> "Apache Cassandra", "type" -> "Column Database"), MongoDBObject("name" -> "Apache HBase", "type" -> "Column Database")) // 検索 // find nosql.find.foreach(doc => println(s"find => $doc")) nosql.find(MongoDBObject("type" -> "Column Database")) .foreach(doc => println(s"find(condition) => $doc")) // findOne // 戻り値はOption nosql.findOne.foreach(doc => println(s"findOne => $doc")) nosql.findOne(MongoDBObject("name" -> "Apache Cassandra")) .foreach(doc => println(s"findOne(condition) => $doc")) // 件数 println("count => " + nosql.count((dbObj: DBObject) => true)) println("count(condition) => " + nosql.count((dbObj: DBObject) => { dbObj("name") == "Apache Cassandra" && dbObj("type") == "Column Database" })) // find.countした方がいい? // println("count => " + nosql.find.count) // println("count(condition) => " + // nosql.find(MongoDBObject("name" -> "Apache Cassandra", // "type" -> "Column Database")).count) // 更新 // $set nosql.update(MongoDBObject("name" -> "MongoDB"), $set ("url" -> "http://www.mongodb.org/")) // $unset nosql.update(MongoDBObject("name" -> "Memcached"), $unset ("type")) // save nosql.save(MongoDBObject("name" -> "Redis", "type" -> "Key Value Store")) nosql.findOne(MongoDBObject("name" -> "Redis")) .foreach(doc => nosql.save(doc += ("url" -> "http://redis.io/"))) // ドキュメントの削除 nosql -= MongoDBObject("name" -> "Apache HBase") // 以下でもOK // nosql.remove(MongoDBObject("name" -> "Apache HBase")) nosql.find.foreach(println) // コレクション内の全データを削除 nosql -= MongoDBObject.empty // 以下でもOK // nosql.remove(MongoDBObject.empty) } finally { mongo.close() } } }
基本的には、共通のimport文をひとつ書いてあげるスタイルのようです。
その他、Scalaのコレクションを拡張した形で実装されてたりしているので、他のドライバよりもちょっと毛色が違いますかね?
ちょっと、APIの使い方に迷う感じです…。
$setみたいな演算子もメソッドとして定義されていて、面白いんですけどね。
こんな感じで。以降使うなら、簡単にGroovyかな…。