From b141f54761ba128eca798798b7409ac0eca66b51 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 2 Apr 2016 13:11:09 +0700 Subject: [PATCH] more DB code rewrite --- modules/challenge/src/main/BSONHandlers.scala | 17 ++-- .../challenge/src/main/ChallengeRepo.scala | 60 +++++++------- modules/db/src/main/CollExt.scala | 5 +- modules/db/src/main/dsl.scala | 1 + modules/game/src/main/GameRepo.scala | 2 +- .../src/main/AggregationPipeline.scala | 74 +++++++++--------- modules/insight/src/main/BSONHandlers.scala | 11 ++- modules/insight/src/main/Dimension.scala | 2 +- modules/insight/src/main/Indexer.scala | 26 +++---- modules/insight/src/main/InsightApi.scala | 4 +- modules/insight/src/main/Storage.scala | 3 +- modules/insight/src/main/UserCache.scala | 13 +--- modules/lobby/src/main/SeekApi.scala | 24 +++--- modules/opening/src/main/Finisher.scala | 17 ++-- modules/opening/src/main/OpeningApi.scala | 40 +++------- modules/opening/src/main/Selector.scala | 33 ++++---- modules/opening/src/main/UserInfos.scala | 3 +- .../perfStat/src/main/PerfStatIndexer.scala | 13 +--- .../perfStat/src/main/PerfStatStorage.scala | 10 +-- modules/puzzle/src/main/Daily.scala | 14 ++-- modules/puzzle/src/main/Finisher.scala | 15 ++-- modules/puzzle/src/main/PuzzleApi.scala | 44 +++++------ modules/puzzle/src/main/Selector.scala | 28 +++---- modules/puzzle/src/main/UserInfos.scala | 2 +- modules/setup/src/main/AnonConfigRepo.scala | 20 ++--- modules/setup/src/main/FilterConfig.scala | 2 - modules/setup/src/main/FormFactory.scala | 1 - modules/setup/src/main/Processor.scala | 1 - modules/setup/src/main/UserConfig.scala | 5 +- modules/setup/src/main/UserConfigRepo.scala | 20 ++--- modules/setup/src/main/package.scala | 9 --- modules/video/src/main/VideoApi.scala | 78 +++++++++---------- 32 files changed, 258 insertions(+), 339 deletions(-) diff --git a/modules/challenge/src/main/BSONHandlers.scala b/modules/challenge/src/main/BSONHandlers.scala index 7e78144f59086..d42d43c9d27f0 100644 --- a/modules/challenge/src/main/BSONHandlers.scala +++ b/modules/challenge/src/main/BSONHandlers.scala @@ -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 { @@ -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] { @@ -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] { diff --git a/modules/challenge/src/main/ChallengeRepo.scala b/modules/challenge/src/main/ChallengeRepo.scala index 49e439f8d6dab..a614f5c985102 100644 --- a/modules/challenge/src/main/ChallengeRepo.scala +++ b/modules/challenge/src/main/ChallengeRepo.scala @@ -1,12 +1,9 @@ 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) { @@ -14,9 +11,9 @@ 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 => @@ -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)) @@ -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) } diff --git a/modules/db/src/main/CollExt.scala b/modules/db/src/main/CollExt.scala index 78add3f481869..2ffdaeec56c3d 100644 --- a/modules/db/src/main/CollExt.scala +++ b/modules/db/src/main/CollExt.scala @@ -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)) diff --git a/modules/db/src/main/dsl.scala b/modules/db/src/main/dsl.scala index c2bf39db556aa..098dd9bda513a 100644 --- a/modules/db/src/main/dsl.scala +++ b/modules/db/src/main/dsl.scala @@ -25,6 +25,7 @@ trait dsl { type Coll = reactivemongo.api.collections.bson.BSONCollection type Bdoc = BSONDocument + type Barr = BSONArray type QueryBuilder = GenericQueryBuilder[BSONSerializationPack.type] diff --git a/modules/game/src/main/GameRepo.scala b/modules/game/src/main/GameRepo.scala index 14e6c4d84c6e1..857047b892223 100644 --- a/modules/game/src/main/GameRepo.scala +++ b/modules/game/src/main/GameRepo.scala @@ -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 diff --git a/modules/insight/src/main/AggregationPipeline.scala b/modules/insight/src/main/AggregationPipeline.scala index 6322d19431a54..e87b96ea49cc6 100644 --- a/modules/insight/src/main/AggregationPipeline.scala +++ b/modules/insight/src/main/AggregationPipeline.scala @@ -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 { @@ -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)) })) @@ -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), @@ -60,17 +60,17 @@ 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] = { @@ -78,11 +78,11 @@ private final class AggregationPipeline { 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 } @@ -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 { @@ -118,15 +118,15 @@ 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 @@ -134,15 +134,15 @@ private final class AggregationPipeline { 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 @@ -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( @@ -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 ) diff --git a/modules/insight/src/main/BSONHandlers.scala b/modules/insight/src/main/BSONHandlers.scala index 1c3a8b1b03ffe..abd653d2b97de 100644 --- a/modules/insight/src/main/BSONHandlers.scala +++ b/modules/insight/src/main/BSONHandlers.scala @@ -5,8 +5,7 @@ import reactivemongo.bson.Macros import chess.{ Role, Color } import lila.db.BSON -import lila.db.BSON._ -import lila.db.Implicits._ +import lila.db.dsl._ import lila.game.BSONHandlers.StatusBSONHandler import lila.rating.PerfType @@ -61,7 +60,7 @@ private object BSONHandlers { def write(e: MaterialRange) = BSONInteger(e.id) } implicit def MoveBSONHandler = new BSON[Move] { - def reads(r: Reader) = Move( + def reads(r: BSON.Reader) = Move( phase = r.get[Phase]("p"), tenths = r.get[Int]("t"), role = r.get[Role]("r"), @@ -71,7 +70,7 @@ private object BSONHandlers { material = r.int("i"), opportunism = r.boolO("o"), luck = r.boolO("l")) - def writes(w: Writer, b: Move) = BSONDocument( + def writes(w: BSON.Writer, b: Move) = BSONDocument( "p" -> b.phase, "t" -> b.tenths, "r" -> b.role, @@ -85,7 +84,7 @@ private object BSONHandlers { implicit def EntryBSONHandler = new BSON[Entry] { import Entry.BSONFields._ - def reads(r: Reader) = Entry( + def reads(r: BSON.Reader) = Entry( id = r.str(id), number = r.int(number), userId = r.str(userId), @@ -104,7 +103,7 @@ private object BSONHandlers { analysed = r.boolD(analysed), provisional = r.boolD(provisional), date = r.date(date)) - def writes(w: Writer, e: Entry) = BSONDocument( + def writes(w: BSON.Writer, e: Entry) = BSONDocument( id -> e.id, number -> e.number, userId -> e.userId, diff --git a/modules/insight/src/main/Dimension.scala b/modules/insight/src/main/Dimension.scala index 84a44984e8531..90a9da7ec5d72 100644 --- a/modules/insight/src/main/Dimension.scala +++ b/modules/insight/src/main/Dimension.scala @@ -4,7 +4,7 @@ import play.twirl.api.Html import reactivemongo.bson._ import chess.{ Color, Role } -import lila.db.Types._ +import lila.db.dsl._ import lila.rating.PerfType sealed abstract class Dimension[A: BSONValueHandler]( diff --git a/modules/insight/src/main/Indexer.scala b/modules/insight/src/main/Indexer.scala index 41402aa5e210f..bd95f4a0606a5 100644 --- a/modules/insight/src/main/Indexer.scala +++ b/modules/insight/src/main/Indexer.scala @@ -3,15 +3,12 @@ package lila.insight import akka.actor.ActorRef import org.joda.time.DateTime import play.api.libs.iteratee._ -import play.api.libs.json.Json import reactivemongo.bson._ import lila.db.dsl._ -import lila.db.BSON._ -import lila.db.Implicits._ +import lila.db.dsl._ import lila.game.BSONHandlers.gameBSONHandler -import lila.game.tube.gameTube -import lila.game.{ Game, Query } +import lila.game.{ Game, GameRepo, Query } import lila.hub.Sequencer import lila.rating.PerfType import lila.user.User @@ -55,10 +52,15 @@ private final class Indexer(storage: Storage, sequencer: ActorRef) { private def fetchFirstGame(user: User): Fu[Option[Game]] = if (user.count.rated == 0) fuccess(none) else { - (user.count.rated >= maxGames) ?? - pimpQB($query(gameQuery(user))).sort(Query.sortCreated).skip(maxGames - 1).one[Game] - } orElse - pimpQB($query(gameQuery(user))).sort(Query.sortChronological).one[Game] + (user.count.rated >= maxGames) ?? GameRepo.coll + .find(gameQuery(user)) + .sort(Query.sortCreated) + .skip(maxGames - 1) + .one[Game] + } orElse GameRepo.coll + .find(gameQuery(user)) + .sort(Query.sortCreated) + .one[Game] private def computeFrom(user: User, from: DateTime, fromNumber: Int): Funit = { storage nbByPerf user.id flatMap { nbs => @@ -71,10 +73,8 @@ private final class Indexer(storage: Storage, sequencer: ActorRef) { e.printStackTrace } map (_.toOption) } - val query = $query(gameQuery(user) ++ Json.obj(Game.BSONFields.createdAt -> $gte($date(from)))) - pimpQB(query) - .sort(Query.sortChronological) - .cursor[Game]() + val query = gameQuery(user) ++ $doc(Game.BSONFields.createdAt $gte from) + GameRepo.sortedCursor(query, Query.sortChronological) .enumerate(maxGames, stopOnError = true) &> Enumeratee.grouped(Iteratee takeUpTo 4) &> Enumeratee.mapM[Seq[Game]].apply[Seq[Entry]] { games => diff --git a/modules/insight/src/main/InsightApi.scala b/modules/insight/src/main/InsightApi.scala index 1c4bb559eb841..c5ae973e4ec4e 100644 --- a/modules/insight/src/main/InsightApi.scala +++ b/modules/insight/src/main/InsightApi.scala @@ -4,7 +4,7 @@ import org.joda.time.DateTime import reactivemongo.api.collections.bson.BSONBatchCommands.AggregationFramework._ import reactivemongo.bson._ -import lila.db.Implicits._ +import lila.db.dsl._ import lila.game.{ Game, GameRepo, Pov } import lila.user.User @@ -39,7 +39,7 @@ final class InsightApi( def userStatus(user: User): Fu[UserStatus] = GameRepo lastFinishedRatedNotFromPosition user flatMap { case None => fuccess(UserStatus.NoGame) - case Some(game) => storage fetchLast user map { + case Some(game) => storage fetchLast user.id map { case None => UserStatus.Empty case Some(entry) if entry.date isBefore game.createdAt => UserStatus.Stale case _ => UserStatus.Fresh diff --git a/modules/insight/src/main/Storage.scala b/modules/insight/src/main/Storage.scala index 0607e4ad2498b..132ebc6099a9b 100644 --- a/modules/insight/src/main/Storage.scala +++ b/modules/insight/src/main/Storage.scala @@ -7,8 +7,7 @@ import reactivemongo.bson._ import scala.concurrent.duration._ import scalaz.NonEmptyList -import lila.db.BSON._ -import lila.db.Implicits._ +import lila.db.dsl._ import lila.user.UserRepo import lila.rating.PerfType diff --git a/modules/insight/src/main/UserCache.scala b/modules/insight/src/main/UserCache.scala index 73cd309807801..ec6eb2061458f 100644 --- a/modules/insight/src/main/UserCache.scala +++ b/modules/insight/src/main/UserCache.scala @@ -1,13 +1,10 @@ package lila.insight import org.joda.time.DateTime -import play.api.libs.iteratee._ import reactivemongo.api.collections.bson.BSONBatchCommands.AggregationFramework._ import reactivemongo.bson._ -import reactivemongo.bson.Macros -import lila.db.BSON._ -import lila.db.Implicits._ +import lila.db.dsl._ case class UserCache( _id: String, // user id @@ -22,11 +19,9 @@ private final class UserCacheApi(coll: Coll) { private implicit val userCacheBSONHandler = Macros.handler[UserCache] - def find(id: String) = coll.find(selectId(id)).one[UserCache] + def find(id: String) = coll.one[UserCache]($id(id)) - def save(u: UserCache) = coll.update(selectId(u.id), u, upsert = true).void + def save(u: UserCache) = coll.update($id(u.id), u, upsert = true).void - def remove(id: String) = coll.remove(selectId(id)).void - - private def selectId(id: String) = BSONDocument("_id" -> id) + def remove(id: String) = coll.remove($id(id)).void } diff --git a/modules/lobby/src/main/SeekApi.scala b/modules/lobby/src/main/SeekApi.scala index 7fdd69d51d01e..fabb5bd5f3aeb 100644 --- a/modules/lobby/src/main/SeekApi.scala +++ b/modules/lobby/src/main/SeekApi.scala @@ -1,13 +1,11 @@ package lila.lobby import org.joda.time.DateTime -import reactivemongo.bson.{ BSONDocument, BSONInteger, BSONRegex, BSONArray, BSONBoolean } import reactivemongo.core.commands._ import scala.concurrent.duration._ import actorApi.LobbyUser -import lila.db.BSON.BSONJodaDateTimeHandler -import lila.db.Types.Coll +import lila.db.dsl._ import lila.memo.AsyncCache import lila.user.{ User, UserRepo } @@ -23,8 +21,8 @@ final class SeekApi( private object ForUser extends CacheKey private def allCursor = - coll.find(BSONDocument()) - .sort(BSONDocument("createdAt" -> -1)) + coll.find($empty) + .sort($doc("createdAt" -> -1)) .cursor[Seek]() private val cache = AsyncCache[CacheKey, List[Seek]]( @@ -58,7 +56,7 @@ final class SeekApi( }._1.reverse def find(id: String): Fu[Option[Seek]] = - coll.find(BSONDocument("_id" -> id)).one[Seek] + coll.find($doc("_id" -> id)).one[Seek] def insert(seek: Seek) = coll.insert(seek) >> findByUser(seek.user.id).flatMap { case seeks if seeks.size <= maxPerUser => funit @@ -67,27 +65,27 @@ final class SeekApi( } >> cache.clear def findByUser(userId: String): Fu[List[Seek]] = - coll.find(BSONDocument("user.id" -> userId)) - .sort(BSONDocument("createdAt" -> -1)) + coll.find($doc("user.id" -> userId)) + .sort($doc("createdAt" -> -1)) .cursor[Seek]().collect[List]() def remove(seek: Seek) = - coll.remove(BSONDocument("_id" -> seek.id)).void >> cache.clear + coll.remove($doc("_id" -> seek.id)).void >> cache.clear def archive(seek: Seek, gameId: String) = { - val archiveDoc = Seek.seekBSONHandler.write(seek) ++ BSONDocument( + val archiveDoc = Seek.seekBSONHandler.write(seek) ++ $doc( "gameId" -> gameId, "archivedAt" -> DateTime.now) - coll.remove(BSONDocument("_id" -> seek.id)).void >> + coll.remove($doc("_id" -> seek.id)).void >> cache.clear >> archiveColl.insert(archiveDoc) } def findArchived(gameId: String): Fu[Option[Seek]] = - archiveColl.find(BSONDocument("gameId" -> gameId)).one[Seek] + archiveColl.find($doc("gameId" -> gameId)).one[Seek] def removeBy(seekId: String, userId: String) = - coll.remove(BSONDocument( + coll.remove($doc( "_id" -> seekId, "user.id" -> userId )).void >> cache.clear diff --git a/modules/opening/src/main/Finisher.scala b/modules/opening/src/main/Finisher.scala index ff73245ec44e5..b5dcea003eab2 100644 --- a/modules/opening/src/main/Finisher.scala +++ b/modules/opening/src/main/Finisher.scala @@ -2,9 +2,8 @@ package lila.opening import org.goochjs.glicko2._ import org.joda.time.DateTime -import reactivemongo.bson.{ BSONDocument, BSONInteger, BSONDouble } -import lila.db.Types.Coll +import lila.db.dsl._ import lila.rating.{ Glicko, Perf } import lila.user.{ User, UserRepo } @@ -34,13 +33,13 @@ private[opening] final class Finisher( userRatingDiff = userPerf.intRating - user.perfs.opening.intRating) ((api.attempt add a) >> { openingColl.update( - BSONDocument("_id" -> opening.id), - BSONDocument("$inc" -> BSONDocument( - Opening.BSONFields.attempts -> BSONInteger(1), - Opening.BSONFields.wins -> BSONInteger(win ? 1 | 0) - )) ++ BSONDocument("$set" -> BSONDocument( - Opening.BSONFields.perf -> Perf.perfBSONHandler.write(openingPerf) - ))) zip UserRepo.setPerf(user.id, "opening", userPerf) + $id(opening.id), + $inc( + Opening.BSONFields.attempts -> $int(1), + Opening.BSONFields.wins -> $int(win ? 1 | 0) + ) ++ $set( + Opening.BSONFields.perf -> Perf.perfBSONHandler.write(openingPerf) + )) zip UserRepo.setPerf(user.id, "opening", userPerf) }) recover lila.db.recoverDuplicateKey(_ => ()) inject (a -> none) } } diff --git a/modules/opening/src/main/OpeningApi.scala b/modules/opening/src/main/OpeningApi.scala index 918f3bcdfd2ee..ea09abed67a0c 100644 --- a/modules/opening/src/main/OpeningApi.scala +++ b/modules/opening/src/main/OpeningApi.scala @@ -3,11 +3,10 @@ package lila.opening import scala.util.{ Try, Success, Failure } import org.joda.time.DateTime -import play.api.libs.json.JsValue -import reactivemongo.bson.{ BSONDocument, BSONInteger, BSONRegex, BSONArray, BSONBoolean } +import reactivemongo.bson.BSONArray import reactivemongo.core.commands._ -import lila.db.Types.Coll +import lila.db.dsl._ import lila.user.{ User, UserRepo } private[opening] final class OpeningApi( @@ -21,39 +20,20 @@ private[opening] final class OpeningApi( object opening { def find(id: Opening.ID): Fu[Option[Opening]] = - openingColl.find(BSONDocument("_id" -> id)).one[Opening] - - def importOne(json: JsValue, token: String): Fu[Opening.ID] = - if (token != apiToken) fufail("Invalid API token") - else { - import Generated.generatedJSONRead - Try(json.as[Generated]) match { - case Failure(err) => fufail(err.getMessage) - case Success(generated) => generated.toOpening.future flatMap insertOpening - } - } - - def insertOpening(opening: Opening.ID => Opening): Fu[Opening.ID] = - lila.db.Util findNextId openingColl flatMap { id => - val o = opening(id) - openingColl.count(BSONDocument("fen" -> o.fen).some) flatMap { - case 0 => openingColl insert o inject o.id - case _ => fufail("Duplicate opening") - } - } + openingColl.byId[Opening](id) } object attempt { def find(openingId: Opening.ID, userId: String): Fu[Option[Attempt]] = - attemptColl.find(BSONDocument( + attemptColl.find($doc( Attempt.BSONFields.id -> Attempt.makeId(openingId, userId) )).one[Attempt] def add(a: Attempt) = attemptColl insert a void def hasPlayed(user: User, opening: Opening): Fu[Boolean] = - attemptColl.count(BSONDocument( + attemptColl.count($doc( Attempt.BSONFields.id -> Attempt.makeId(opening.id, user.id) ).some) map (0!=) @@ -62,9 +42,9 @@ private[opening] final class OpeningApi( import reactivemongo.api.collections.bson.BSONBatchCommands.AggregationFramework.{ Group, Limit, Match, Push } val playedIdsGroup = - Group(BSONBoolean(true))("ids" -> Push(Attempt.BSONFields.openingId)) + Group($boolean(true))("ids" -> Push(Attempt.BSONFields.openingId)) - col.aggregate(Match(BSONDocument(Attempt.BSONFields.userId -> user.id)), + col.aggregate(Match($doc(Attempt.BSONFields.userId -> user.id)), List(Limit(max), playedIdsGroup)).map(_.documents.headOption.flatMap( _.getAs[BSONArray]("ids")).getOrElse(BSONArray())) } @@ -72,9 +52,9 @@ private[opening] final class OpeningApi( object identify { def apply(fen: String, max: Int): Fu[List[String]] = nameColl.find( - BSONDocument("_id" -> fen), - BSONDocument("_id" -> false) - ).one[BSONDocument] map { obj => + $doc("_id" -> fen), + $doc("_id" -> false) + ).one[Bdoc] map { obj => ~obj.??(_.getAs[List[String]]("names")) } } diff --git a/modules/opening/src/main/Selector.scala b/modules/opening/src/main/Selector.scala index 2f829d4ba340b..7174c0b467027 100644 --- a/modules/opening/src/main/Selector.scala +++ b/modules/opening/src/main/Selector.scala @@ -1,12 +1,10 @@ package lila.opening +import reactivemongo.bson.BSONArray import scala.concurrent.duration._ import scala.util.Random -import reactivemongo.api.QueryOpts -import reactivemongo.bson.{ BSONDocument, BSONInteger, BSONArray } - -import lila.db.Types.Coll +import lila.db.dsl._ import lila.user.User private[opening] final class Selector( @@ -20,8 +18,8 @@ private[opening] final class Selector( def apply(me: Option[User]): Fu[Opening] = (me match { case None => - openingColl.find(BSONDocument()) - .options(QueryOpts(skipN = Random nextInt anonSkipMax)) + openingColl.find($empty) + .skip(Random nextInt anonSkipMax) .one[Opening] flatten "Can't find a opening for anon player!" case Some(user) => api.attempt.playedIds(user, modulo) flatMap { ids => tryRange(user, toleranceStep, ids) @@ -31,16 +29,15 @@ private[opening] final class Selector( }).mon(_.opening.selector.time) >>- lila.mon.opening.selector.count() private def tryRange(user: User, tolerance: Int, ids: BSONArray): Fu[Opening] = - openingColl.find(BSONDocument( - Opening.BSONFields.id -> BSONDocument("$nin" -> ids), - Opening.BSONFields.rating -> BSONDocument( - "$gt" -> BSONInteger(user.perfs.opening.intRating - tolerance), - "$lt" -> BSONInteger(user.perfs.opening.intRating + tolerance) - ) - )).one[Opening] flatMap { - case Some(opening) => fuccess(opening) - case None => if ((tolerance + toleranceStep) <= toleranceMax) - tryRange(user, tolerance + toleranceStep, ids) - else fufail(s"Can't find a opening for user $user!") - } + openingColl.one[Opening]($doc( + Opening.BSONFields.id $nin ids, + Opening.BSONFields.rating $gt + (user.perfs.opening.intRating - tolerance) $lt + (user.perfs.opening.intRating + tolerance) + )) flatMap { + case Some(opening) => fuccess(opening) + case None => if ((tolerance + toleranceStep) <= toleranceMax) + tryRange(user, tolerance + toleranceStep, ids) + else fufail(s"Can't find a opening for user $user!") + } } diff --git a/modules/opening/src/main/UserInfos.scala b/modules/opening/src/main/UserInfos.scala index 3af25628d7bc1..3d29d6a5f01c5 100644 --- a/modules/opening/src/main/UserInfos.scala +++ b/modules/opening/src/main/UserInfos.scala @@ -2,9 +2,8 @@ package lila.opening import play.api.libs.json._ import reactivemongo.bson._ -import reactivemongo.bson.Macros -import lila.db.Types.Coll +import lila.db.dsl._ import lila.rating.Glicko import lila.user.User diff --git a/modules/perfStat/src/main/PerfStatIndexer.scala b/modules/perfStat/src/main/PerfStatIndexer.scala index 76e8619fa1d84..d523e84252312 100644 --- a/modules/perfStat/src/main/PerfStatIndexer.scala +++ b/modules/perfStat/src/main/PerfStatIndexer.scala @@ -4,8 +4,7 @@ import akka.actor.ActorRef import play.api.libs.iteratee._ import lila.db.dsl._ -import lila.db.Implicits._ -import lila.game.{ Game, Pov, Query } +import lila.game.{ Game, GameRepo, Pov, Query } import lila.hub.Sequencer import lila.rating.PerfType import lila.user.User @@ -21,16 +20,12 @@ final class PerfStatIndexer(storage: PerfStatStorage, sequencer: ActorRef) { } private def compute(user: User, perfType: PerfType): Funit = { - import lila.game.tube.gameTube - import lila.game.BSONHandlers.gameBSONHandler - pimpQB($query { + GameRepo.sortedCursor( Query.user(user.id) ++ Query.finished ++ Query.turnsMoreThan(2) ++ - Query.variant(PerfType variantOf perfType) - - }).sort(Query.sortChronological) - .cursor[Game]() + Query.variant(PerfType variantOf perfType), + Query.sortChronological) .enumerate(Int.MaxValue, stopOnError = true) |>>> Iteratee.fold[Game, PerfStat](PerfStat.init(user.id, perfType)) { case (perfStat, game) if game.perfType.contains(perfType) => diff --git a/modules/perfStat/src/main/PerfStatStorage.scala b/modules/perfStat/src/main/PerfStatStorage.scala index 27b4d47facf8d..2cbe3b358c4a2 100644 --- a/modules/perfStat/src/main/PerfStatStorage.scala +++ b/modules/perfStat/src/main/PerfStatStorage.scala @@ -2,17 +2,13 @@ package lila.perfStat import org.joda.time.DateTime import reactivemongo.bson._ -import reactivemongo.bson.Macros import scala.concurrent.duration._ -import lila.db.BSON._ -import lila.db.Types.Coll +import lila.db.dsl._ import lila.rating.PerfType final class PerfStatStorage(coll: Coll) { - import lila.db.BSON.BSONJodaDateTimeHandler - import reactivemongo.bson.Macros implicit val PerfTypeBSONHandler = new BSONHandler[BSONInteger, PerfType] { def read(b: BSONInteger) = PerfType.byId get b.value err s"Invalid perf type id ${b.value}" def write(p: PerfType) = BSONInteger(p.id) @@ -33,10 +29,10 @@ final class PerfStatStorage(coll: Coll) { private implicit val PerfStatBSONHandler = Macros.handler[PerfStat] def find(userId: String, perfType: PerfType): Fu[Option[PerfStat]] = - coll.find(BSONDocument("_id" -> PerfStat.makeId(userId, perfType))).one[PerfStat] + coll.byId[PerfStat](PerfStat.makeId(userId, perfType)) def update(perfStat: PerfStat): Funit = - coll.update(BSONDocument("_id" -> perfStat.id), perfStat).void + coll.update($id(perfStat.id), perfStat).void def insert(perfStat: PerfStat): Funit = coll.insert(perfStat).void diff --git a/modules/puzzle/src/main/Daily.scala b/modules/puzzle/src/main/Daily.scala index 677a285b50437..a80e33830586c 100644 --- a/modules/puzzle/src/main/Daily.scala +++ b/modules/puzzle/src/main/Daily.scala @@ -5,10 +5,8 @@ import scala.concurrent.duration._ import akka.actor.{ ActorSelection, Scheduler } import akka.pattern.ask import org.joda.time.DateTime -import reactivemongo.bson.BSONDocument -import lila.db.BSON.BSONJodaDateTimeHandler -import lila.db.Types.Coll +import lila.db.dsl._ private[puzzle] final class Daily( coll: Coll, @@ -45,15 +43,15 @@ private[puzzle] final class Daily( } private def findCurrent = coll.find( - BSONDocument("day" -> BSONDocument("$gt" -> DateTime.now.minusMinutes(24 * 60 - 15))) + $doc("day" -> $doc("$gt" -> DateTime.now.minusMinutes(24 * 60 - 15))) ).one[Puzzle] private def findNew = coll.find( - BSONDocument("day" -> BSONDocument("$exists" -> false)) - ).sort(BSONDocument("vote.sum" -> -1)).one[Puzzle] flatMap { + $doc("day" -> $doc("$exists" -> false)) + ).sort($doc("vote.sum" -> -1)).one[Puzzle] flatMap { case Some(puzzle) => coll.update( - BSONDocument("_id" -> puzzle.id), - BSONDocument("$set" -> BSONDocument("day" -> DateTime.now)) + $doc("_id" -> puzzle.id), + $doc("$set" -> $doc("day" -> DateTime.now)) ) inject puzzle.some case None => fuccess(none) } diff --git a/modules/puzzle/src/main/Finisher.scala b/modules/puzzle/src/main/Finisher.scala index d2587c4328b45..43c51c560a77f 100644 --- a/modules/puzzle/src/main/Finisher.scala +++ b/modules/puzzle/src/main/Finisher.scala @@ -2,9 +2,8 @@ package lila.puzzle import org.goochjs.glicko2._ import org.joda.time.DateTime -import reactivemongo.bson.{ BSONDocument, BSONInteger } -import lila.db.Types.Coll +import lila.db.dsl._ import lila.rating.{ Glicko, Perf } import lila.user.{ User, UserRepo } @@ -38,13 +37,13 @@ private[puzzle] final class Finisher( userRatingDiff = userPerf.intRating - user.perfs.puzzle.intRating) ((api.attempt add a) >> { puzzleColl.update( - BSONDocument("_id" -> puzzle.id), - BSONDocument("$inc" -> BSONDocument( - Puzzle.BSONFields.attempts -> BSONInteger(1), - Puzzle.BSONFields.wins -> BSONInteger(data.isWin ? 1 | 0) - )) ++ BSONDocument("$set" -> BSONDocument( + $id(puzzle.id), + $inc( + Puzzle.BSONFields.attempts -> $int(1), + Puzzle.BSONFields.wins -> $int(data.isWin ? 1 | 0) + ) ++ $set( Puzzle.BSONFields.perf -> Perf.perfBSONHandler.write(puzzlePerf) - ))) zip UserRepo.setPerf(user.id, "puzzle", userPerf) + )) zip UserRepo.setPerf(user.id, "puzzle", userPerf) }) recover lila.db.recoverDuplicateKey(_ => ()) inject (a -> none) } diff --git a/modules/puzzle/src/main/PuzzleApi.scala b/modules/puzzle/src/main/PuzzleApi.scala index 525925f21342e..163deb0cc5946 100644 --- a/modules/puzzle/src/main/PuzzleApi.scala +++ b/modules/puzzle/src/main/PuzzleApi.scala @@ -5,9 +5,9 @@ import scala.util.{ Try, Success, Failure } import org.joda.time.DateTime import play.api.libs.json.JsValue import reactivemongo.api.collections.bson.BSONBatchCommands.AggregationFramework._ -import reactivemongo.bson.{ BSONDocument, BSONInteger, BSONRegex, BSONArray, BSONBoolean } +import reactivemongo.bson. BSONArray -import lila.db.Types.Coll +import lila.db.dsl._ import lila.user.{ User, UserRepo } private[puzzle] final class PuzzleApi( @@ -20,11 +20,11 @@ private[puzzle] final class PuzzleApi( object puzzle { def find(id: PuzzleId): Fu[Option[Puzzle]] = - puzzleColl.find(BSONDocument("_id" -> id)).one[Puzzle] + puzzleColl.find($doc("_id" -> id)).one[Puzzle] def latest(nb: Int): Fu[List[Puzzle]] = - puzzleColl.find(BSONDocument()) - .sort(BSONDocument("date" -> -1)) + puzzleColl.find($empty) + .sort($doc("date" -> -1)) .cursor[Puzzle]() .collect[List](nb) @@ -43,8 +43,8 @@ private[puzzle] final class PuzzleApi( case Success(puzzle) :: rest => lila.db.Util findNextId puzzleColl flatMap { id => val p = puzzle(id) val fenStart = p.fen.split(' ').take(2).mkString(" ") - puzzleColl.count(BSONDocument( - "fen" -> BSONRegex(fenStart.replace("/", "\\/"), "") + puzzleColl.count($doc( + "fen".$regex(fenStart.replace("/", "\\/"), "") ).some) flatMap { case 0 => (puzzleColl insert p) >> { insertPuzzles(rest) map (Success(id) :: _) @@ -55,22 +55,22 @@ private[puzzle] final class PuzzleApi( } def export(nb: Int): Fu[List[Puzzle]] = List(true, false).map { mate => - puzzleColl.find(BSONDocument("mate" -> mate)) - .sort(BSONDocument(Puzzle.BSONFields.voteSum -> -1)) + puzzleColl.find($doc("mate" -> mate)) + .sort($doc(Puzzle.BSONFields.voteSum -> -1)) .cursor[Puzzle]().collect[List](nb / 2) }.sequenceFu.map(_.flatten) def disable(id: PuzzleId): Funit = puzzleColl.update( - BSONDocument("_id" -> id), - BSONDocument("$set" -> BSONDocument(Puzzle.BSONFields.vote -> Vote.disable)) + $doc("_id" -> id), + $doc("$set" -> $doc(Puzzle.BSONFields.vote -> Vote.disable)) ).void } object attempt { def find(puzzleId: PuzzleId, userId: String): Fu[Option[Attempt]] = - attemptColl.find(BSONDocument( + attemptColl.find($doc( Attempt.BSONFields.id -> Attempt.makeId(puzzleId, userId) )).one[Attempt] @@ -83,11 +83,11 @@ private[puzzle] final class PuzzleApi( } val a2 = a1.copy(vote = v.some) attemptColl.update( - BSONDocument("_id" -> a2.id), - BSONDocument("$set" -> BSONDocument(Attempt.BSONFields.vote -> v))) zip + $doc("_id" -> a2.id), + $doc("$set" -> $doc(Attempt.BSONFields.vote -> v))) zip puzzleColl.update( - BSONDocument("_id" -> p2.id), - BSONDocument("$set" -> BSONDocument(Puzzle.BSONFields.vote -> p2.vote))) map { + $doc("_id" -> p2.id), + $doc("$set" -> $doc(Puzzle.BSONFields.vote -> p2.vote))) map { case _ => p2 -> a2 } } @@ -95,22 +95,22 @@ private[puzzle] final class PuzzleApi( def add(a: Attempt) = attemptColl insert a void def hasPlayed(user: User, puzzle: Puzzle): Fu[Boolean] = - attemptColl.count(BSONDocument( + attemptColl.count($doc( Attempt.BSONFields.id -> Attempt.makeId(puzzle.id, user.id) ).some) map (0!=) def playedIds(user: User, max: Int): Fu[BSONArray] = attemptColl.distinct(Attempt.BSONFields.puzzleId, - BSONDocument(Attempt.BSONFields.userId -> user.id).some + $doc(Attempt.BSONFields.userId -> user.id).some ) map BSONArray.apply def hasVoted(user: User): Fu[Boolean] = attemptColl.find( - BSONDocument(Attempt.BSONFields.userId -> user.id), - BSONDocument( + $doc(Attempt.BSONFields.userId -> user.id), + $doc( Attempt.BSONFields.vote -> true, Attempt.BSONFields.id -> false - )).sort(BSONDocument(Attempt.BSONFields.date -> -1)) - .cursor[BSONDocument]() + )).sort($doc(Attempt.BSONFields.date -> -1)) + .cursor[Bdoc]() .collect[List](5) map { case attempts if attempts.size < 5 => true case attempts => attempts.foldLeft(false) { diff --git a/modules/puzzle/src/main/Selector.scala b/modules/puzzle/src/main/Selector.scala index 5d2151e96edab..18d4dc03b8f18 100644 --- a/modules/puzzle/src/main/Selector.scala +++ b/modules/puzzle/src/main/Selector.scala @@ -3,10 +3,7 @@ package lila.puzzle import scala.concurrent.duration._ import scala.util.Random -import reactivemongo.api.QueryOpts -import reactivemongo.bson.{ BSONDocument, BSONInteger, BSONArray } - -import lila.db.Types.Coll +import lila.db.dsl._ import lila.user.User private[puzzle] final class Selector( @@ -15,10 +12,10 @@ private[puzzle] final class Selector( anonMinRating: Int, maxAttempts: Int) { - private def popularSelector(mate: Boolean) = BSONDocument( - Puzzle.BSONFields.voteSum -> BSONDocument("$gt" -> BSONInteger(mate.fold(anonMinRating, 0)))) + private def popularSelector(mate: Boolean) = $doc( + Puzzle.BSONFields.voteSum $gt mate.fold(anonMinRating, 0)) - private def mateSelector(mate: Boolean) = BSONDocument("mate" -> mate) + private def mateSelector(mate: Boolean) = $doc("mate" -> mate) private def difficultyDecay(difficulty: Int) = difficulty match { case 1 => -200 @@ -36,7 +33,7 @@ private[puzzle] final class Selector( me match { case None => puzzleColl.find(popularSelector(isMate) ++ mateSelector(isMate)) - .options(QueryOpts(skipN = Random nextInt anonSkipMax)) + .skip(Random nextInt anonSkipMax) .one[Puzzle] case Some(user) if user.perfs.puzzle.nb > maxAttempts => fuccess(none) case Some(user) => @@ -55,14 +52,13 @@ private[puzzle] final class Selector( case d => 200 } - private def tryRange(rating: Int, tolerance: Int, step: Int, decay: Int, ids: BSONArray, isMate: Boolean): Fu[Option[Puzzle]] = - puzzleColl.find(mateSelector(isMate) ++ BSONDocument( - Puzzle.BSONFields.id -> BSONDocument("$nin" -> ids), - Puzzle.BSONFields.rating -> BSONDocument( - "$gt" -> BSONInteger(rating - tolerance + decay), - "$lt" -> BSONInteger(rating + tolerance + decay) - ) - )).sort(BSONDocument(Puzzle.BSONFields.voteSum -> -1)) + private def tryRange(rating: Int, tolerance: Int, step: Int, decay: Int, ids: Barr, isMate: Boolean): Fu[Option[Puzzle]] = + puzzleColl.find(mateSelector(isMate) ++ $doc( + Puzzle.BSONFields.id $nin ids, + Puzzle.BSONFields.rating $gt + (rating - tolerance + decay) $lt + (rating + tolerance + decay) + )).sort($sort desc Puzzle.BSONFields.voteSum) .one[Puzzle] flatMap { case None if (tolerance + step) <= toleranceMax => tryRange(rating, tolerance + step, step, decay, ids, isMate) diff --git a/modules/puzzle/src/main/UserInfos.scala b/modules/puzzle/src/main/UserInfos.scala index 710dbc020c8b2..d7a37f46384ec 100644 --- a/modules/puzzle/src/main/UserInfos.scala +++ b/modules/puzzle/src/main/UserInfos.scala @@ -3,7 +3,7 @@ package lila.puzzle import play.api.libs.json._ import reactivemongo.bson._ -import lila.db.Types.Coll +import lila.db.dsl._ import lila.rating.Glicko import lila.user.User diff --git a/modules/setup/src/main/AnonConfigRepo.scala b/modules/setup/src/main/AnonConfigRepo.scala index 080ac2dec5fcf..c0ed4a7002aa5 100644 --- a/modules/setup/src/main/AnonConfigRepo.scala +++ b/modules/setup/src/main/AnonConfigRepo.scala @@ -6,18 +6,19 @@ import reactivemongo.bson._ import lila.common.{ LilaCookie, LilaException } import lila.db.dsl._ -import lila.db.Implicits._ import lila.game.Game import lila.user.User -import tube.anonConfigTube private[setup] object AnonConfigRepo { + // dirty + private val coll = Env.current.anonConfigColl + def update(req: RequestHeader)(f: UserConfig => UserConfig): Funit = configOption(req) flatMap { _ ?? { config => - anonConfigTube.coll.update( - BSONDocument("_id" -> config.id), + coll.update( + $doc("_id" -> config.id), f(config), upsert = true).void } @@ -27,8 +28,8 @@ private[setup] object AnonConfigRepo { configOption(req) map (_ | UserConfig.default("nocookie")) def config(sid: String): Fu[UserConfig] = - $find byId sid recover { - case e: LilaException => { + coll.byId[UserConfig](sid) recover { + case e: Exception => { logger.warn("Can't load config", e) none[UserConfig] } @@ -38,12 +39,7 @@ private[setup] object AnonConfigRepo { sessionId(req).??(s => config(s) map (_.some)) def filter(req: RequestHeader): Fu[FilterConfig] = sessionId(req) ?? { sid => - anonConfigTube.coll.find( - BSONDocument("_id" -> sid), - BSONDocument("filter" -> true) - ).one[BSONDocument] map { - _ flatMap (_.getAs[FilterConfig]("filter")) - } + coll.primitiveOne[FilterConfig]($id(sid), "filter") } map (_ | FilterConfig.default) private def sessionId(req: RequestHeader): Option[String] = diff --git a/modules/setup/src/main/FilterConfig.scala b/modules/setup/src/main/FilterConfig.scala index 1c0e3743aa80e..c2dc9e35d3899 100644 --- a/modules/setup/src/main/FilterConfig.scala +++ b/modules/setup/src/main/FilterConfig.scala @@ -74,6 +74,4 @@ object FilterConfig { "s" -> o.speed.map(_.id), "e" -> o.ratingRange.toString) } - - private[setup] val tube = lila.db.BsTube(filterConfigBSONHandler) } diff --git a/modules/setup/src/main/FormFactory.scala b/modules/setup/src/main/FormFactory.scala index a0fe5bc12218b..bd829ddab72e7 100644 --- a/modules/setup/src/main/FormFactory.scala +++ b/modules/setup/src/main/FormFactory.scala @@ -6,7 +6,6 @@ import lila.lobby.Color import lila.user.UserContext import play.api.data._ import play.api.data.Forms._ -import tube.{ userConfigTube, anonConfigTube } private[setup] final class FormFactory(casualOnly: Boolean) { diff --git a/modules/setup/src/main/Processor.scala b/modules/setup/src/main/Processor.scala index bd2f7826fe9dc..327a2ac8c4f41 100644 --- a/modules/setup/src/main/Processor.scala +++ b/modules/setup/src/main/Processor.scala @@ -12,7 +12,6 @@ import lila.lobby.actorApi.{ AddHook, AddSeek } import lila.lobby.Hook import lila.user.{ User, UserContext } import makeTimeout.short -import tube.{ userConfigTube, anonConfigTube } private[setup] final class Processor( lobby: ActorSelection, diff --git a/modules/setup/src/main/UserConfig.scala b/modules/setup/src/main/UserConfig.scala index 90810d13070b0..4d91f995602f3 100644 --- a/modules/setup/src/main/UserConfig.scala +++ b/modules/setup/src/main/UserConfig.scala @@ -29,7 +29,8 @@ private[setup] object UserConfig { hook = HookConfig.default, filter = FilterConfig.default) - import lila.db.{ BsTube, BSON } + import lila.db.BSON + import lila.db.dsl._ import reactivemongo.bson._ import AiConfig.aiConfigBSONHandler import FriendConfig.friendConfigBSONHandler @@ -52,6 +53,4 @@ private[setup] object UserConfig { "hook" -> o.hook, "filter" -> o.filter) } - - private[setup] val tube = BsTube(userConfigBSONHandler) } diff --git a/modules/setup/src/main/UserConfigRepo.scala b/modules/setup/src/main/UserConfigRepo.scala index 94cac4fa0b631..e73571f7fde88 100644 --- a/modules/setup/src/main/UserConfigRepo.scala +++ b/modules/setup/src/main/UserConfigRepo.scala @@ -5,34 +5,30 @@ import reactivemongo.bson._ import lila.common.LilaException import lila.db.dsl._ -import lila.db.Implicits._ import lila.game.Game import lila.user.User -import tube.userConfigTube private[setup] object UserConfigRepo { + // dirty + private val coll = Env.current.userConfigColl + def update(user: User)(f: UserConfig => UserConfig): Funit = config(user) flatMap { config => - userConfigTube.coll.update( - BSONDocument("_id" -> config.id), + coll.update( + $doc("_id" -> config.id), f(config), upsert = true).void } def config(user: User): Fu[UserConfig] = - $find byId user.id recover { - case e: LilaException => { + coll.byId[UserConfig](user.id) recover { + case e: Exception => { logger.warn("Can't load config", e) none[UserConfig] } } map (_ | UserConfig.default(user.id)) def filter(user: User): Fu[FilterConfig] = - userConfigTube.coll.find( - BSONDocument("_id" -> user.id), - BSONDocument("filter" -> true) - ).one[BSONDocument] map { - _ flatMap (_.getAs[FilterConfig]("filter")) getOrElse FilterConfig.default - } + coll.primitiveOne[FilterConfig]($id(user.id), "filter") map (_ | FilterConfig.default) } diff --git a/modules/setup/src/main/package.scala b/modules/setup/src/main/package.scala index ff1f318fc1ee5..5d9b72c58e54c 100644 --- a/modules/setup/src/main/package.scala +++ b/modules/setup/src/main/package.scala @@ -4,14 +4,5 @@ import lila.socket.WithSocket package object setup extends PackageObject with WithPlay with WithSocket { - object tube { - - private[setup] implicit lazy val userConfigTube = - UserConfig.tube inColl Env.current.userConfigColl - - private[setup] implicit lazy val anonConfigTube = - UserConfig.tube inColl Env.current.anonConfigColl - } - private[setup] def logger = lila.log("setup") } diff --git a/modules/video/src/main/VideoApi.scala b/modules/video/src/main/VideoApi.scala index 4f8374a224441..a97c67b052a08 100644 --- a/modules/video/src/main/VideoApi.scala +++ b/modules/video/src/main/VideoApi.scala @@ -6,8 +6,8 @@ import reactivemongo.core.commands._ import scala.concurrent.duration._ import lila.common.paginator._ -import lila.db.paginator.BSONAdapter -import lila.db.Types.Coll +import lila.db.dsl._ +import lila.db.paginator.Adapter import lila.memo.AsyncCache import lila.user.{ User, UserRepo } @@ -41,16 +41,16 @@ private[video] final class VideoApi( private val maxPerPage = 18 def find(id: Video.ID): Fu[Option[Video]] = - videoColl.find(BSONDocument("_id" -> id)).one[Video] + videoColl.find($doc("_id" -> id)).one[Video] def search(user: Option[User], query: String, page: Int): Fu[Paginator[VideoView]] = { val q = query.split(' ').map { word => s""""$word"""" } mkString " " - val textScore = BSONDocument("score" -> BSONDocument("$meta" -> "textScore")) + val textScore = $doc("score" -> $doc("$meta" -> "textScore")) Paginator( - adapter = new BSONAdapter[Video]( + adapter = new Adapter[Video]( collection = videoColl, - selector = BSONDocument( - "$text" -> BSONDocument("$search" -> q) + selector = $doc( + "$text" -> $doc("$search" -> q) ), projection = textScore, sort = textScore @@ -61,19 +61,19 @@ private[video] final class VideoApi( def save(video: Video): Funit = videoColl.update( - BSONDocument("_id" -> video.id), - BSONDocument("$set" -> video), + $doc("_id" -> video.id), + $doc("$set" -> video), upsert = true).void def removeNotIn(ids: List[Video.ID]) = videoColl.remove( - BSONDocument("_id" -> BSONDocument("$nin" -> ids)) + $doc("_id" -> $doc("$nin" -> ids)) ).void def setMetadata(id: Video.ID, metadata: Youtube.Metadata) = videoColl.update( - BSONDocument("_id" -> id), - BSONDocument("$set" -> BSONDocument("metadata" -> metadata)), + $doc("_id" -> id), + $doc("$set" -> $doc("metadata" -> metadata)), upsert = false ).void @@ -81,11 +81,11 @@ private[video] final class VideoApi( videoColl.distinct("_id", none) map lila.db.BSON.asStrings def popular(user: Option[User], page: Int): Fu[Paginator[VideoView]] = Paginator( - adapter = new BSONAdapter[Video]( + adapter = new Adapter[Video]( collection = videoColl, - selector = BSONDocument(), - projection = BSONDocument(), - sort = BSONDocument("metadata.likes" -> -1) + selector = $empty, + projection = $empty, + sort = $doc("metadata.likes" -> -1) ) mapFutureList videoViews(user), currentPage = page, maxPerPage = maxPerPage) @@ -93,35 +93,31 @@ private[video] final class VideoApi( def byTags(user: Option[User], tags: List[Tag], page: Int): Fu[Paginator[VideoView]] = if (tags.isEmpty) popular(user, page) else Paginator( - adapter = new BSONAdapter[Video]( + adapter = new Adapter[Video]( collection = videoColl, - selector = BSONDocument( - "tags" -> BSONDocument("$all" -> tags) - ), - projection = BSONDocument(), - sort = BSONDocument("metadata.likes" -> -1) + selector = $doc("tags" $all tags), + projection = $empty, + sort = $doc("metadata.likes" -> -1) ) mapFutureList videoViews(user), currentPage = page, maxPerPage = maxPerPage) def byAuthor(user: Option[User], author: String, page: Int): Fu[Paginator[VideoView]] = Paginator( - adapter = new BSONAdapter[Video]( + adapter = new Adapter[Video]( collection = videoColl, - selector = BSONDocument( - "author" -> author - ), - projection = BSONDocument(), - sort = BSONDocument("metadata.likes" -> -1) + selector = $doc("author" -> author), + projection = $empty, + sort = $doc("metadata.likes" -> -1) ) mapFutureList videoViews(user), currentPage = page, maxPerPage = maxPerPage) def similar(user: Option[User], video: Video, max: Int): Fu[Seq[VideoView]] = - videoColl.find(BSONDocument( - "tags" -> BSONDocument("$in" -> video.tags), - "_id" -> BSONDocument("$ne" -> video.id) - )).sort(BSONDocument("metadata.likes" -> -1)) + videoColl.find($doc( + "tags" $in video.tags, + "_id" $ne video.id + )).sort($doc("metadata.likes" -> -1)) .cursor[Video]() .collect[List]().map { videos => videos.sortBy { v => -v.similarity(video) } take max @@ -142,7 +138,7 @@ private[video] final class VideoApi( object view { def find(videoId: Video.ID, userId: String): Fu[Option[View]] = - viewColl.find(BSONDocument( + viewColl.find($doc( View.BSONFields.id -> View.makeId(videoId, userId) )).one[View] @@ -150,17 +146,15 @@ private[video] final class VideoApi( lila.db.recoverDuplicateKey(_ => ()) def hasSeen(user: User, video: Video): Fu[Boolean] = - viewColl.count(BSONDocument( + viewColl.count($doc( View.BSONFields.id -> View.makeId(video.id, user.id) ).some) map (0!=) def seenVideoIds(user: User, videos: Seq[Video]): Fu[Set[Video.ID]] = viewColl.distinct(View.BSONFields.videoId, - BSONDocument( - "_id" -> BSONDocument("$in" -> videos.map { v => - View.makeId(v.id, user.id) - }) - ).some) map lila.db.BSON.asStringSet + $inIds(videos.map { v => + View.makeId(v.id, user.id) + }).some) map lila.db.BSON.asStringSet } object tag { @@ -182,8 +176,8 @@ private[video] final class VideoApi( tags.filterNot(_.isNumeric) } else videoColl.aggregate( - Match(BSONDocument("tags" -> BSONDocument("$all" -> filterTags))), - List(Project(BSONDocument("tags" -> BSONBoolean(true))), + Match($doc("tags" $all filterTags)), + List(Project($doc("tags" -> true)), Unwind("tags"), GroupField("tags")("nb" -> SumValue(1)))).map( _.documents.flatMap(_.asOpt[TagNb])) @@ -208,7 +202,7 @@ private[video] final class VideoApi( private val popularCache = AsyncCache.single[List[TagNb]]( f = videoColl.aggregate( - Project(BSONDocument("tags" -> BSONBoolean(true))), List( + Project($doc("tags" -> true)), List( Unwind("tags"), GroupField("tags")("nb" -> SumValue(1)), Sort(Descending("nb")))).map( _.documents.flatMap(_.asOpt[TagNb])),