MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Mapowanie dokumentów MongoDB do klasy spraw z typami, ale bez osadzonych dokumentów

Tak, to możliwe. W rzeczywistości jest to nawet prostsze niż posiadanie poddokumentu „użytkownika” w „tweecie”. Kiedy "użytkownik" jest referencją, jest to tylko wartość skalarna, MongoDB i "Podzbiór" nie mają mechanizmów do odpytywania pól poddokumentów.

Przygotowałem dla Ciebie prosty fragment kodu REPLable (zakłada się, że masz dwie kolekcje - "tweety" i "użytkownicy").

Przygotowania...

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"

Nasz User klasa przypadku

case class User(_id: ObjectId, name: String)

Szereg pól na tweety i użytkownika

val content = "content".fieldOf[String]
val user = "user".fieldOf[User]
val name = "name".fieldOf[String]

Tutaj zaczynają się dziać bardziej skomplikowane rzeczy. Potrzebujemy ValueReader który jest w stanie uzyskać ObjectId na podstawie nazwy pola, ale następnie przechodzi do innej kolekcji i odczytuje stamtąd obiekt.

Można to napisać jako pojedynczy fragment kodu, który robi wszystko na raz (możesz zobaczyć taki wariant w historii odpowiedzi), ale bardziej idiomatyczne byłoby wyrażenie tego jako kombinacja czytelników. Załóżmy, że mamy ValueReader[User] który czyta z DBObject :

val userFromDBObject = ValueReader({
  case DocumentId(id) ~ name(name) => User(id, name)
})

To, co pozostało, to ogólny ValueReader[T] który oczekuje ObjectId i pobiera obiekt z określonej kolekcji za pomocą dostarczonego czytnika bazowego:

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

Następnie możemy powiedzieć, że nasza klasa typu do odczytu User s z referencji to tylko

implicit val userReader = new RefReader[User](users, userFromDBObject)

A tak byś tego używał:

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. Listy baz danych MongoDB z podanym prefiksem w Go

  2. Mongoose:Nie można pobrać dokumentów plików z kolekcji .chunk bez pola danych

  3. Zaktualizuj wiele w manguście

  4. Limit czasu połączenia MongoDB z MongoLab w NodeJS na Heroku

  5. Generuj PDF za pomocą biblioteki JasperReports i MongoDB