MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Съпоставяне на MongoDB документи към клас case с типове, но без вградени документи

Да, възможно е. Всъщност е дори по-просто, отколкото да имате поддокумент "потребител" в "туит". Когато „потребител“ е препратка, това е просто скаларна стойност, MongoDB и „Подмножество“ нямат механизми за заявка към полета на поддокумент.

Подготвих за вас прост REPLable кодов фрагмент (предполага, че имате две колекции – „туитове“ и „потребители“).

Подготовка...

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))
}


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Как да настроите FeatureCompatibilityVersion в MongoDB

  2. Липсва синтаксис; преди изявление в mongoexport

  3. Как можете да дебъгвате съхранени javascript функции в MongoDB?

  4. Не може да се свърже с MongoDb (чрез удостоверяване) с помощта на mongocsharpdriver 2.7.0

  5. Грешка:queryTxt ETIMEOUT при свързване към MongoDb Atlas с помощта на mongoose