MongoDBをScalaから使うための公式ドライバ (Mongo Scala Driver)

# 0. はじめに

[Mongo Scala Driver](http://mongodb.github.io/mongo-scala-driver/) は、MongoDB を Scala から使うための公式なドライバです。

非同期システムで動かすことが意識されており、Observerパターンで Trait が定義されています。

従来MongoDBの公式Scalaドライバとされていた [Casbah](https://mongodb.github.io/casbah/) とは、全く使い勝手が異なり、Observerパターンに不慣れだと、戸惑うこともあるかと思い、基本的な使い方をまとめておきます。[公式サンプルコード](https://github.com/mongodb/mongo-scala-driver/tree/master/examples/src/test/scala/tour)を簡略化したような内容になっています。

# 1. 準備

## 検証環境

- Mac OS X El Capitan Version 10.11.3
- Scala 2.11.7
- MongoDB 3.2.1
- Mongo Scala Driver 1.1.0

## インストール

sbtを使ってインストールします。

```
libraryDependencies ++= Seq(
  "org.mongodb.scala" %% "mongo-scala-driver" % "1.1.+"
)
```

## ファイル構成

ファイル構成としては、下記のようにして検証しました。

```
test
 ├ Helpers.scala
 └ MongoDB.scala
```

### Helpers.scala

面倒なObserver周りの処理を隠蔽するためにHelperオブジェクトを作ります。

resultsメソッドでクエリを実行して、結果をSeqで返しています。

```scala
package test

import java.util.concurrent.TimeUnit

import org.mongodb.scala.{Completed, Document, Observable}

import scala.concurrent.Await
import scala.concurrent.duration.Duration

object Helpers {

  implicit class DocumentObservable[C](val observable: Observable[Document]) extends ImplicitObservable[Document]

  implicit class CompletedObservable[C](val observable: Observable[Completed]) extends ImplicitObservable[Completed]

  trait ImplicitObservable[C] {
    val observable: Observable[C]

    def results: Seq[C] = Await.result(observable.toFuture(), Duration(10, TimeUnit.SECONDS))
  }
}
```

### MongoDB.scala

実際にドライバの使い方を検証していくためのオブジェクトを定義しています。

```scala
package test

import org.mongodb.scala._

import test.Helpers._

object MongoDB {

  def main(args: Array[String]) {
  	// 検証コード
  }
}

```

# 2. よく使いそうなメソッド

## 2.1. DBに接続してCollectionオブジェクトを取得する

ここでは、Collection名をproductsとして検証を進めます。

```scala
// Localで稼働中のMongoDBに接続する
val mongoClient: MongoClient = MongoClient()

// Databaseを取得する
val database: MongoDatabase = mongoClient.getDatabase("mydb")

// Collectionを取得する
val products: MongoCollection[Document] = database.getCollection("products")
```

## 2.2. CollectionをDropする: `drop`

```scala
// CollectionをDropして初期化する
products.drop.results
```
## 2.3. インサート系メソッド

### Documentを1件インサートする: `insertOne`

```scala
val doc1: Document = Document("name" -> "MongoDB", "type" -> "database", "count" -> 1, "info" -> Document("x" -> 203, "y" -> 102))
products.insertOne(doc1).results.foreach(println)
```

### DocumentをN件インサートする: `insertMany`

```scala
// Bulk INSERT
val doc2 = (1 to 100) map { i: Int => Document("name" -> i) }
products.insertMany(doc2).results.foreach(println)
```

## 2.4. 参照系メソッド

### 全件参照: `find`

```scala
products.find.results.foreach(r => println(r.toJson))
```
### 最初の1件目を参照: `find.first`

```scala
products.find.first.results.foreach(r => println(r.toJson))
```
### 条件を指定して参照

#### Documentで条件を指定: `find(doc3)`

```scala
// SELECT * FROM products WHERE name = "MongoDB"
val doc3 = Document("name" -> "MongoDB")
products.find(doc3).results.foreach(r => println(r.toJson))
```

#### フィルタで条件を指定: `and`, `gt`, `lte`, etc.

```scala
products.find(and(gt("name", 50), lte("name", 60))).results.foreach(r => println(r.toJson))
```
## 2.5. リソースを開放する

```scala
mongoClient.close
```

# 3. 参考にしたドキュメント

だいたいこんな感じです。網羅的な解説としては、下記を確認してみてください。

- [公式ドキュメント](http://mongodb.github.io/mongo-scala-driver/1.1/)
- [サンプルコード](https://github.com/mongodb/mongo-scala-driver/tree/master/examples/src/test/scala/tour)