Si es posible. En realidad, es incluso más simple que tener un subdocumento de "usuario" en un "tweet". Cuando "usuario" es una referencia, es solo un valor escalar, MongoDB y "Subconjunto" no tienen mecanismos para consultar campos de subdocumentos.
He preparado un fragmento de código REPLable simple para usted (se supone que tiene dos colecciones:"tweets" y "users").
Preparativos...
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"
Nuestro User
clase de caso
case class User(_id: ObjectId, name: String)
Una serie de campos para tweets y usuario
val content = "content".fieldOf[String]
val user = "user".fieldOf[User]
val name = "name".fieldOf[String]
Aquí empiezan a pasar cosas más complicadas. Lo que necesitamos es un ValueReader
que es capaz de obtener ObjectId
basado en el nombre del campo, pero luego va a otra colección y lee un objeto desde allí.
Esto se puede escribir como una sola pieza de código, que hace todo a la vez (es posible que vea una variante de este tipo en el historial de respuestas), pero sería más idiomático expresarlo como una combinación de lectores. Supongamos que tenemos un ValueReader[User]
que lee desde DBObject
:
val userFromDBObject = ValueReader({
case DocumentId(id) ~ name(name) => User(id, name)
})
Lo que queda es un ValueReader[T]
genérico que espera ObjectId
y recupera un objeto de una colección específica utilizando el lector subyacente proporcionado:
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
}
}
Entonces, podemos decir nuestra clase de tipo para leer User
s de las referencias es simplemente
implicit val userReader = new RefReader[User](users, userFromDBObject)
Y así es como lo usarías:
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))
}