lila/modules/db/src/main/PaginatorAdapter.scala

89 lines
2.4 KiB
Scala
Raw Normal View History

2013-03-13 15:41:43 -06:00
package lila.db
package paginator
2016-04-01 05:41:57 -06:00
import dsl._
2016-03-02 06:13:36 -07:00
import reactivemongo.api._
2019-11-29 11:08:13 -07:00
import reactivemongo.api.bson._
import scala.util.chaining._
2013-03-13 15:41:43 -06:00
2013-05-24 11:04:49 -06:00
import lila.common.paginator.AdapterLike
2013-03-25 11:28:31 -06:00
final class CachedAdapter[A](
adapter: AdapterLike[A],
val nbResults: Fu[Int]
)(implicit ec: scala.concurrent.ExecutionContext)
extends AdapterLike[A] {
2013-03-13 15:41:43 -06:00
def slice(offset: Int, length: Int): Fu[Seq[A]] =
2013-03-25 11:28:31 -06:00
adapter.slice(offset, length)
2013-03-13 15:41:43 -06:00
}
2014-07-03 12:57:37 -06:00
2016-04-01 10:43:50 -06:00
final class Adapter[A: BSONDocumentReader](
collection: Coll,
selector: Bdoc,
2019-11-29 15:11:03 -07:00
projection: Option[Bdoc],
sort: Bdoc,
readPreference: ReadPreference = ReadPreference.primary,
hint: Option[Bdoc] = None
)(implicit ec: scala.concurrent.ExecutionContext)
extends AdapterLike[A] {
2014-07-03 12:57:37 -06:00
2019-11-29 15:11:03 -07:00
def nbResults: Fu[Int] = collection.secondaryPreferred.countSel(selector)
2014-07-03 12:57:37 -06:00
def slice(offset: Int, length: Int): Fu[List[A]] =
2019-12-13 07:30:20 -07:00
collection
.find(selector, projection)
2014-07-03 12:57:37 -06:00
.sort(sort)
2016-04-01 10:43:50 -06:00
.skip(offset)
.pipe { query =>
hint match {
case None => query
2020-07-19 07:11:06 -06:00
case Some(h) => query.hint(collection hint h)
}
}
2020-07-19 07:11:06 -06:00
.cursor[A](readPreference)
.list(length)
}
2018-11-27 20:51:12 -07:00
/*
2019-09-20 08:47:23 -06:00
* because mongodb mapReduce doesn't support `skip`, slice requires two queries.
2018-11-27 20:51:12 -07:00
* The first one gets the IDs with `skip`.
* The second one runs the mapReduce on these IDs.
* This avoid running mapReduce on many unnecessary docs.
* NOTE: Requires string ID.
*/
final class MapReduceAdapter[A: BSONDocumentReader](
collection: Coll,
selector: Bdoc,
2018-11-27 20:51:12 -07:00
sort: Bdoc,
runCommand: RunCommand,
2018-11-27 20:51:12 -07:00
command: Bdoc,
readPreference: ReadPreference = ReadPreference.primary
)(implicit ec: scala.concurrent.ExecutionContext)
extends AdapterLike[A] {
2019-11-29 15:11:03 -07:00
def nbResults: Fu[Int] = collection.secondaryPreferred.countSel(selector)
def slice(offset: Int, length: Int): Fu[List[A]] =
2019-12-13 07:30:20 -07:00
collection
.find(selector, $id(true).some)
2018-11-27 20:51:12 -07:00
.sort(sort)
.skip(offset)
2020-07-19 07:11:06 -06:00
.cursor[Bdoc](readPreference)
.list(length)
2019-11-29 11:08:13 -07:00
.dmap { _ flatMap { _.getAsOpt[BSONString]("_id") } }
2018-11-27 20:51:12 -07:00
.flatMap { ids =>
runCommand(
$doc(
"mapreduce" -> collection.name,
2019-12-13 07:30:20 -07:00
"query" -> $inIds(ids),
"sort" -> sort,
"out" -> $doc("inline" -> true)
2018-11-27 20:51:12 -07:00
) ++ command,
readPreference
) map { res =>
2019-12-13 07:30:20 -07:00
res.getAsOpt[List[Bdoc]]("results").??(_ flatMap implicitly[BSONDocumentReader[A]].readOpt)
}
}
}