Skip to content

Commit

Permalink
more DB code rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Apr 2, 2016
1 parent a6ee522 commit b141f54
Show file tree
Hide file tree
Showing 32 changed files with 258 additions and 339 deletions.
17 changes: 8 additions & 9 deletions modules/challenge/src/main/BSONHandlers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import reactivemongo.bson._
import chess.Mode
import chess.variant.Variant
import lila.db.BSON
import lila.db.BSON._
import lila.db.BSON.BSONJodaDateTimeHandler
import lila.db.Implicits._
import lila.db.BSON.{ Reader, Writer }
import lila.db.dsl._
import lila.rating.PerfType

private object BSONHandlers {
Expand Down Expand Up @@ -37,9 +36,9 @@ private object BSONHandlers {
r intO "d" map TimeControl.Correspondence.apply
} getOrElse TimeControl.Unlimited
def writes(w: Writer, t: TimeControl) = t match {
case TimeControl.Clock(l, i) => BSONDocument("l" -> l, "i" -> i)
case TimeControl.Correspondence(d) => BSONDocument("d" -> d)
case TimeControl.Unlimited => BSONDocument()
case TimeControl.Clock(l, i) => $doc("l" -> l, "i" -> i)
case TimeControl.Correspondence(d) => $doc("d" -> d)
case TimeControl.Unlimited => $empty
}
}
implicit val VariantBSONHandler = new BSONHandler[BSONInteger, Variant] {
Expand All @@ -56,19 +55,19 @@ private object BSONHandlers {
}
implicit val RatingBSONHandler = new BSON[Rating] {
def reads(r: Reader) = Rating(r.int("i"), r.boolD("p"))
def writes(w: Writer, r: Rating) = BSONDocument(
def writes(w: Writer, r: Rating) = $doc(
"i" -> r.int,
"p" -> w.boolO(r.provisional))
}
implicit val RegisteredBSONHandler = new BSON[Registered] {
def reads(r: Reader) = Registered(r.str("id"), r.get[Rating]("r"))
def writes(w: Writer, r: Registered) = BSONDocument(
def writes(w: Writer, r: Registered) = $doc(
"id" -> r.id,
"r" -> r.rating)
}
implicit val AnonymousBSONHandler = new BSON[Anonymous] {
def reads(r: Reader) = Anonymous(r.str("s"))
def writes(w: Writer, a: Anonymous) = BSONDocument(
def writes(w: Writer, a: Anonymous) = $doc(
"s" -> a.secret)
}
implicit val EitherChallengerBSONHandler = new BSON[EitherChallenger] {
Expand Down
60 changes: 28 additions & 32 deletions modules/challenge/src/main/ChallengeRepo.scala
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
package lila.challenge

import org.joda.time.DateTime
import reactivemongo.bson.{ BSONDocument, BSONInteger, BSONRegex, BSONArray, BSONBoolean }
import scala.concurrent.duration._

import lila.db.BSON.BSONJodaDateTimeHandler
import lila.db.Implicits.LilaBSONDocumentZero
import lila.db.Types.Coll
import lila.db.dsl._
import lila.user.{ User, UserRepo }

private final class ChallengeRepo(coll: Coll, maxPerUser: Int) {

import BSONHandlers._
import Challenge._

def byId(id: Challenge.ID) = coll.find(selectId(id)).one[Challenge]
def byId(id: Challenge.ID) = coll.find($id(id)).one[Challenge]

def exists(id: Challenge.ID) = coll.count(selectId(id).some).map(0<)
def exists(id: Challenge.ID) = coll.count($id(id).some).map(0<)

def insert(c: Challenge): Funit =
coll.insert(c) >> c.challenger.right.toOption.?? { challenger =>
Expand All @@ -27,55 +24,55 @@ private final class ChallengeRepo(coll: Coll, maxPerUser: Int) {
}

def createdByChallengerId(userId: String): Fu[List[Challenge]] =
coll.find(selectCreated ++ BSONDocument("challenger.id" -> userId))
.sort(BSONDocument("createdAt" -> 1))
coll.find(selectCreated ++ $doc("challenger.id" -> userId))
.sort($doc("createdAt" -> 1))
.cursor[Challenge]().collect[List]()

def createdByDestId(userId: String): Fu[List[Challenge]] =
coll.find(selectCreated ++ BSONDocument("destUser.id" -> userId))
.sort(BSONDocument("createdAt" -> 1))
coll.find(selectCreated ++ $doc("destUser.id" -> userId))
.sort($doc("createdAt" -> 1))
.cursor[Challenge]().collect[List]()

def removeByUserId(userId: String): Funit =
coll.remove(BSONDocument("$or" -> BSONArray(
BSONDocument("challenger.id" -> userId),
BSONDocument("destUser.id" -> userId)
coll.remove($doc("$or" -> $arr(
$doc("challenger.id" -> userId),
$doc("destUser.id" -> userId)
))).void

def like(c: Challenge) = ~(for {
challengerId <- c.challengerUserId
destUserId <- c.destUserId
if c.active
} yield coll.find(selectCreated ++ BSONDocument(
} yield coll.find(selectCreated ++ $doc(
"challenger.id" -> challengerId,
"destUser.id" -> destUserId)).one[Challenge])

private[challenge] def countCreatedByDestId(userId: String): Fu[Int] =
coll.count(Some(selectCreated ++ BSONDocument("destUser.id" -> userId)))
coll.count(Some(selectCreated ++ $doc("destUser.id" -> userId)))

private[challenge] def realTimeUnseenSince(date: DateTime, max: Int): Fu[List[Challenge]] =
coll.find(selectCreated ++ selectClock ++ BSONDocument(
"seenAt" -> BSONDocument("$lt" -> date)
coll.find(selectCreated ++ selectClock ++ $doc(
"seenAt" -> $doc("$lt" -> date)
)).cursor[Challenge]().collect[List](max)

private[challenge] def expiredIds(max: Int): Fu[List[Challenge.ID]] =
coll.distinct(
"_id",
BSONDocument("expiresAt" -> BSONDocument("$lt" -> DateTime.now)).some
$doc("expiresAt" -> $doc("$lt" -> DateTime.now)).some
) map lila.db.BSON.asStrings

def setSeenAgain(id: Challenge.ID) = coll.update(
selectId(id),
BSONDocument(
"$set" -> BSONDocument(
$id(id),
$doc(
"$set" -> $doc(
"status" -> Status.Created.id,
"seenAt" -> DateTime.now,
"expiresAt" -> inTwoWeeks))
).void

def setSeen(id: Challenge.ID) = coll.update(
selectId(id),
BSONDocument("$set" -> BSONDocument("seenAt" -> DateTime.now))
$id(id),
$doc("$set" -> $doc("seenAt" -> DateTime.now))
).void

def offline(challenge: Challenge) = setStatus(challenge, Status.Offline, Some(_ plusHours 3))
Expand All @@ -84,25 +81,24 @@ private final class ChallengeRepo(coll: Coll, maxPerUser: Int) {
def accept(challenge: Challenge) = setStatus(challenge, Status.Accepted, Some(_ plusHours 3))

def statusById(id: Challenge.ID) = coll.find(
selectId(id),
BSONDocument("status" -> true, "_id" -> false)
).one[BSONDocument].map { _.flatMap(_.getAs[Status]("status")) }
$id(id),
$doc("status" -> true, "_id" -> false)
).one[Bdoc].map { _.flatMap(_.getAs[Status]("status")) }

private def setStatus(
challenge: Challenge,
status: Status,
expiresAt: Option[DateTime => DateTime] = None) = coll.update(
selectCreated ++ selectId(challenge.id),
BSONDocument("$set" -> BSONDocument(
selectCreated ++ $id(challenge.id),
$doc("$set" -> $doc(
"status" -> status.id,
"expiresAt" -> expiresAt.fold(inTwoWeeks) { _(DateTime.now) }
))
).void

private[challenge] def remove(id: Challenge.ID) = coll.remove(selectId(id)).void
private[challenge] def remove(id: Challenge.ID) = coll.remove($id(id)).void

private def selectId(id: Challenge.ID) = BSONDocument("_id" -> id)
private val selectCreated = BSONDocument("status" -> Status.Created.id)
private val selectClock = BSONDocument("timeControl.l" -> BSONDocument("$exists" -> true))
private val selectCreated = $doc("status" -> Status.Created.id)
private val selectClock = $doc("timeControl.l" $exists true)
}

5 changes: 3 additions & 2 deletions modules/db/src/main/CollExt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ trait CollExt {
def byId[D: BSONDocumentReader, I: BSONValueWriter](id: I): Fu[Option[D]] =
one[D]($id(id))

def byId[D: BSONDocumentReader](id: String): Fu[Option[D]] =
one[D]($id(id))
def byId[D: BSONDocumentReader](id: String): Fu[Option[D]] = one[D]($id(id))

def byId[D: BSONDocumentReader](id: Int): Fu[Option[D]] = one[D]($id(id))

def byIds[D: BSONDocumentReader, I: BSONValueWriter](ids: Iterable[I]): Fu[List[D]] =
list[D]($inIds(ids))
Expand Down
1 change: 1 addition & 0 deletions modules/db/src/main/dsl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ trait dsl {

type Coll = reactivemongo.api.collections.bson.BSONCollection
type Bdoc = BSONDocument
type Barr = BSONArray

type QueryBuilder = GenericQueryBuilder[BSONSerializationPack.type]

Expand Down
2 changes: 1 addition & 1 deletion modules/game/src/main/GameRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import lila.user.{ User, UidNb }
object GameRepo {

// dirty
private val coll = Env.current.gameColl
val coll = Env.current.gameColl

type ID = String

Expand Down
74 changes: 37 additions & 37 deletions modules/insight/src/main/AggregationPipeline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import reactivemongo.api.collections.bson.BSONBatchCommands.AggregationFramework
import reactivemongo.bson._
import scalaz.NonEmptyList

import lila.db.Implicits._
import lila.db.dsl._

private final class AggregationPipeline {

Expand All @@ -14,20 +14,20 @@ private final class AggregationPipeline {

private lazy val movetimeIdDispatcher =
MovetimeRange.reversedNoInf.foldLeft[BSONValue](BSONInteger(MovetimeRange.MTRInf.id)) {
case (acc, mtr) => BSONDocument(
"$cond" -> BSONArray(
BSONDocument("$lte" -> BSONArray("$" + F.moves("t"), mtr.tenths.last)),
case (acc, mtr) => $doc(
"$cond" -> $arr(
$doc("$lte" -> $arr("$" + F.moves("t"), mtr.tenths.last)),
mtr.id,
acc))
}
private lazy val materialIdDispatcher = BSONDocument(
"$cond" -> BSONArray(
BSONDocument("$eq" -> BSONArray("$" + F.moves("i"), 0)),
private lazy val materialIdDispatcher = $doc(
"$cond" -> $arr(
$doc("$eq" -> $arr("$" + F.moves("i"), 0)),
MaterialRange.Equal.id,
MaterialRange.reversedButEqualAndLast.foldLeft[BSONValue](BSONInteger(MaterialRange.Up4.id)) {
case (acc, mat) => BSONDocument(
"$cond" -> BSONArray(
BSONDocument(mat.negative.fold("$lt", "$lte") -> BSONArray("$" + F.moves("i"), mat.imbalance)),
case (acc, mat) => $doc(
"$cond" -> $arr(
$doc(mat.negative.fold("$lt", "$lte") -> $arr("$" + F.moves("i"), mat.imbalance)),
mat.id,
acc))
}))
Expand All @@ -48,7 +48,7 @@ private final class AggregationPipeline {
"nb" -> SumValue(1),
"ids" -> AddToSet("_id")
).some
private def groupMulti(d: Dimension[_], metricDbKey: String) = Group(BSONDocument(
private def groupMulti(d: Dimension[_], metricDbKey: String) = Group($doc(
"dimension" -> dimensionGroupId(d),
"metric" -> ("$" + metricDbKey)))(
"v" -> SumValue(1),
Expand All @@ -60,29 +60,29 @@ private final class AggregationPipeline {
"stack" -> PushMulti(
"metric" -> "_id.metric",
"v" -> "v")).some
private val sliceIds = Project(BSONDocument(
private val sliceIds = Project($doc(
"_id" -> true,
"v" -> true,
"nb" -> true,
"ids" -> BSONDocument("$slice" -> BSONArray("$ids", 4))
"ids" -> $doc("$slice" -> $arr("$ids", 4))
)).some
private val sliceStackedIds = Project(BSONDocument(
private val sliceStackedIds = Project($doc(
"_id" -> true,
"nb" -> true,
"stack" -> true,
"ids" -> BSONDocument("$slice" -> BSONArray("$ids", 4))
"ids" -> $doc("$slice" -> $arr("$ids", 4))
)).some

def apply(question: Question[_], userId: String): NonEmptyList[PipelineOperator] = {
import question.{ dimension, metric, filters }
val gameMatcher = combineDocs(question.filters.collect {
case f if f.dimension.isInGame => f.matcher
})
def matchMoves(extraMatcher: BSONDocument = BSONDocument()) =
def matchMoves(extraMatcher: Bdoc = $empty) =
combineDocs(extraMatcher :: question.filters.collect {
case f if f.dimension.isInMove => f.matcher
}).some.filterNot(_.isEmpty) map Match
def projectForMove = Project(BSONDocument({
def projectForMove = Project($doc({
metric.dbKey :: dimension.dbKey :: filters.collect {
case Filter(d, _) if d.isInMove => d.dbKey
}
Expand All @@ -92,10 +92,10 @@ private final class AggregationPipeline {
Match(
selectUserId(userId) ++
gameMatcher ++
(dimension == Dimension.Opening).??(BSONDocument(F.eco -> BSONDocument("$exists" -> true))) ++
Metric.requiresAnalysis(metric).??(BSONDocument(F.analysed -> true)) ++
(dimension == Dimension.Opening).??($doc(F.eco -> $doc("$exists" -> true))) ++
Metric.requiresAnalysis(metric).??($doc(F.analysed -> true)) ++
(Metric.requiresStableRating(metric) || Dimension.requiresStableRating(dimension)).?? {
BSONDocument(F.provisional -> BSONDocument("$ne" -> true))
$doc(F.provisional -> $doc("$ne" -> true))
}
),
/* sortDate :: */ sampleGames :: ((metric match {
Expand All @@ -118,31 +118,31 @@ private final class AggregationPipeline {
case M.Opportunism => List(
projectForMove,
unwindMoves,
matchMoves(BSONDocument(F.moves("o") -> BSONDocument("$exists" -> true))),
matchMoves($doc(F.moves("o") -> $doc("$exists" -> true))),
sampleMoves,
group(dimension, GroupFunction("$push", BSONDocument(
"$cond" -> BSONArray("$" + F.moves("o"), 1, 0)
group(dimension, GroupFunction("$push", $doc(
"$cond" -> $arr("$" + F.moves("o"), 1, 0)
))),
sliceIds,
Project(BSONDocument(
Project($doc(
"_id" -> true,
"v" -> BSONDocument("$multiply" -> BSONArray(100, BSONDocument("$avg" -> "$v"))),
"v" -> $doc("$multiply" -> $arr(100, $doc("$avg" -> "$v"))),
"nb" -> true,
"ids" -> true
)).some
)
case M.Luck => List(
projectForMove,
unwindMoves,
matchMoves(BSONDocument(F.moves("l") -> BSONDocument("$exists" -> true))),
matchMoves($doc(F.moves("l") -> $doc("$exists" -> true))),
sampleMoves,
group(dimension, GroupFunction("$push", BSONDocument(
"$cond" -> BSONArray("$" + F.moves("l"), 1, 0)
group(dimension, GroupFunction("$push", $doc(
"$cond" -> $arr("$" + F.moves("l"), 1, 0)
))),
sliceIds,
Project(BSONDocument(
Project($doc(
"_id" -> true,
"v" -> BSONDocument("$multiply" -> BSONArray(100, BSONDocument("$avg" -> "$v"))),
"v" -> $doc("$multiply" -> $arr(100, $doc("$avg" -> "$v"))),
"nb" -> true,
"ids" -> true
)).some
Expand All @@ -153,17 +153,17 @@ private final class AggregationPipeline {
matchMoves(),
sampleMoves,
group(dimension, SumValue(1)),
Project(BSONDocument(
Project($doc(
"v" -> true,
"ids" -> true,
"nb" -> BSONDocument("$size" -> "$ids")
"nb" -> $doc("$size" -> "$ids")
)).some,
Project(BSONDocument(
"v" -> BSONDocument(
"$divide" -> BSONArray("$v", "$nb")
Project($doc(
"v" -> $doc(
"$divide" -> $arr("$v", "$nb")
),
"nb" -> true,
"ids" -> BSONDocument("$slice" -> BSONArray("$ids", 4))
"ids" -> $doc("$slice" -> $arr("$ids", 4))
)).some
)
case M.Movetime => List(
Expand All @@ -172,7 +172,7 @@ private final class AggregationPipeline {
matchMoves(),
sampleMoves,
group(dimension, GroupFunction("$avg",
BSONDocument("$divide" -> BSONArray("$" + F.moves("t"), 10))
$doc("$divide" -> $arr("$" + F.moves("t"), 10))
)),
sliceIds
)
Expand Down
Loading

0 comments on commit b141f54

Please sign in to comment.