Skip to content

Instantly share code, notes, and snippets.

@dt
Created September 22, 2011 21:44
Show Gist options
  • Save dt/1236140 to your computer and use it in GitHub Desktop.
Save dt/1236140 to your computer and use it in GitHub Desktop.
Priming via types?
trait Finder[RecordType] {
def findAll(ids: Seq[Long]): Seq[RecordType] = Nil
def find(id: Long): Option[RecordType] = None
}
abstract class Bar { def id: Long } ; object Bar extends Finder[Bar]
abstract class Baz { def id: Long } ; object Baz extends Finder[Baz]
abstract class Foo {
def id: Long
def barId: Long // this could be here as a MongoForeignObjectId thanks to a Bar.FK trait too
def bazId: Long
// these can lead to N+1. kill 'em.
//def bar: Option[Bar] = Bar.find(barId)
//def baz: Option[Baz] = Baz.find(bazId)
}; object Foo extends Finder[Foo]
object BadExample {
// with the above impl of .bar, this would be N+1. bad.
// List[Foo]().map{ f => f.bar }
// List[Foo]().map{ f => f.baz }
}
class BarPrimed[T <: Foo](b: Option[Bar], foo: T) extends FooWrapper(foo) {
def bar = b
}
class BazPrimed[T <: Foo](b: Option[Baz], foo: T) extends FooWrapper(foo) {
def baz = b
}
class FooWrapper(foo: Foo) extends Foo {
def id = foo.id
def barId = foo.barId
def bazId = foo.bazId
}
object BadExample2 {
// with the above impl of .bar, this would be N+1. bad.
val ex1: Seq[Bar] = primeBars(List[Foo]()).flatMap{ f => f.bar }
val ex2: Seq[Baz] = primeBazs(List[Foo]()).flatMap{ f => f.baz }
val a = List[Foo]()
val b = primeBars(a).filter(_.bar.isDefined)
val c = primeBazs(b).filter(_.baz.isDefined)
val d = c.map(_.bar)
def primeBars[T <: Foo](fooList: Seq[T]): Seq[BarPrimed[T]] = {
val ids = Bar.findAll( fooList.map(_.barId) ).groupBy(_.id).mapValues(_.headOption)
fooList.map( foo => new BarPrimed(ids.get(foo.barId).getOrElse(None), foo) )
}
def primeBazs[T <: Foo](fooList: Seq[T]): Seq[BazPrimed[T]] = {
val ids = Baz.findAll( fooList.map(_.bazId) ).groupBy(_.id).mapValues(_.headOption)
fooList.map( foo => new BazPrimed(ids.get(foo.bazId).getOrElse(None), foo) )
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment