sql >> Databáze >  >> NoSQL >> MongoDB

Mapování dokumentů MongoDB na třídu případů s typy, ale bez vložených dokumentů

Ano, je to možné. Ve skutečnosti je to ještě jednodušší než mít „uživatelský“ dílčí dokument v „tweetu“. Když je "user" odkaz, je to jen skalární hodnota, MongoDB a "Subset" nemají žádné mechanismy pro dotazování na pole vnořených dokumentů.

Připravil jsem pro vás jednoduchý REPLable fragment kódu (předpokládá, že máte dvě kolekce -- "tweets" a "users").

Přípravy...

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"

Náš User třída případu

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

Řada polí pro tweety a uživatele

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

Zde se začnou dít složitější věci. Potřebujeme ValueReader který je schopen získat ObjectId na základě názvu pole, ale pak přejde do jiné kolekce a přečte objekt odtud.

To lze napsat jako jeden kus kódu, který dělá všechny věci najednou (takovou variantu můžete vidět v historii odpovědí), ale bylo by idiomatičtější vyjádřit to jako kombinaci čteček. Předpokládejme, že máme ValueReader[User] který čte z DBObject :

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

Co zbývá, je obecný ValueReader[T] který očekává ObjectId a načte objekt ze specifické kolekce pomocí dodané základní čtečky:

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

Pak můžeme říci, že naše třída typu pro čtení User s z referencí je pouze

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

A takto byste to použili:

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. Jak donutit MongoDB pullAll ignorovat pořadí dokumentů

  2. Zapomněli jste datovou cestu mongodb

  3. MongoDB a MongoJS - nemohou spustit runCommand pro textové dotazy

  4. MongoDB – operátor $setIsSubset nepracuje s $match stage