sql >> Database >  >> NoSQL >> MongoDB

MongoDB-documenten toewijzen aan casusklasse met typen maar zonder ingesloten documenten

Ja het is mogelijk. Eigenlijk is het zelfs nog eenvoudiger dan een "gebruiker"-subdocument in een "tweet" te hebben. Wanneer "gebruiker" een referentie is, is het slechts een scalaire waarde, MongoDB en "Subset" hebben geen mechanismen om subdocumentvelden te doorzoeken.

Ik heb een eenvoudig REPLable codefragment voor je gemaakt (er wordt aangenomen dat je twee verzamelingen hebt -- "tweets" en "users").

Voorbereidingen...

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"

Onze User zaakklasse

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

Een aantal velden voor tweets en gebruiker

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

Hier beginnen meer gecompliceerde dingen te gebeuren. Wat we nodig hebben is een ValueReader die in staat is om ObjectId . te krijgen gebaseerd op veldnaam, maar gaat dan naar een andere verzameling en leest daar een object.

Dit kan worden geschreven als een enkel stuk code, dat alle dingen tegelijk doet (je ziet mogelijk een dergelijke variant in de antwoordgeschiedenis), maar het zou idiomatischer zijn om het uit te drukken als een combinatie van lezers. Stel dat we een ValueReader[User] . hebben dat leest uit DBObject :

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

Wat overblijft is een generieke ValueReader[T] die ObjectId . verwacht en haalt een object op uit een specifieke collectie met behulp van de meegeleverde onderliggende lezer:

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

Dan kunnen we onze typeklasse zeggen voor het lezen van User s van referenties is slechts

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

En zo zou je het gebruiken:

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. MongoDB jsonSchema validatie additionalProperties

  2. Hoe maak je een lijst van alle Redis-databases?

  3. Hoe MongoDB te schalen?

  4. Spring Boot met Session/Redis-serialisatiefout met slechte Active Directory Ldap-referenties