はい、可能です。実際には、「ツイート」に「ユーザー」サブドキュメントを含めるよりも簡単です。 「user」が参照である場合、それは単なるスカラー値であり、MongoDBおよび「Subset」にはサブドキュメントフィールドをクエリするメカニズムがありません。
簡単なREPLableコードスニペットを用意しました(「ツイート」と「ユーザー」の2つのコレクションがあることを前提としています)。
準備...
import org.bson.types.ObjectId
import com.mongodb._
import com.osinka.subset._
import Document.DocumentId
val db = new Mongo("localhost") getDB "test"
val tweets = db getCollection "tweets"
val users = db getCollection "users"
User
ケースクラス
case class User(_id: ObjectId, name: String)
ツイートとユーザーのフィールドの数
val content = "content".fieldOf[String]
val user = "user".fieldOf[User]
val name = "name".fieldOf[String]
ここで、より複雑なことが起こり始めます。必要なのはValueReader
です ObjectId
を取得することができます フィールド名に基づいていますが、別のコレクションに移動して、そこからオブジェクトを読み取ります。
これは、すべてのことを一度に実行する単一のコードとして記述できます(回答履歴にそのようなバリアントが表示される場合があります)が、リーダーの組み合わせとして表現する方が慣用的です。 ValueReader[User]
があるとします。 DBObject
から読み取ります :
val userFromDBObject = ValueReader({
case DocumentId(id) ~ name(name) => User(id, name)
})
残っているのは一般的なValueReader[T]
ObjectId
を期待します 提供されている基礎となるリーダーを使用して、特定のコレクションからオブジェクトを取得します。
class RefReader[T](val collection: DBCollection, val underlying: ValueReader[T]) extends ValueReader[T] {
override def unpack(o: Any):Option[T] =
o match {
case id: ObjectId =>
Option(collection findOne id) flatMap {underlying.unpack _}
case _ =>
None
}
}
次に、User
を読み取るための型クラスと言います。 参照からのsは単に
implicit val userReader = new RefReader[User](users, userFromDBObject)
そして、これはあなたがそれを使う方法です:
import collection.JavaConverters._
tweets.find.iterator.asScala foreach {
case Document.DocumentId(id) ~ content(content) ~ user(u) =>
println("%s - %s by %s".format(id, content, u))
}