All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.mongocamp.driver.mongodb.pagination.MongoPaginatedAggregation.scala Maven / Gradle / Ivy

There is a newer version: 2.8.1
Show newest version
package dev.mongocamp.driver.mongodb.pagination

import com.mongodb.client.model.Facet
import dev.mongocamp.driver.mongodb.exception.MongoCampPaginationException
import dev.mongocamp.driver.mongodb.{ MongoDAO, _ }
import org.mongodb.scala.bson.Document
import org.mongodb.scala.bson.conversions.Bson
import org.mongodb.scala.model.Aggregates

import scala.jdk.CollectionConverters._

case class MongoPaginatedAggregation[A <: Any](
    dao: MongoDAO[A],
    aggregationPipeline: List[Bson] = List(),
    allowDiskUse: Boolean = false,
    maxWait: Int = DefaultMaxWait
) extends MongoPagination[Document] {

  private val AggregationKeyMetaData      = "metadata"
  private val AggregationKeyData          = "data"
  private val AggregationKeyMetaDataTotal = "total"

  def paginate(page: Long, rows: Long): PaginationResult[Document] = {
    if (rows <= 0) {
      throw MongoCampPaginationException("rows per page must be greater then 0.")
    }
    if (page <= 0) {
      throw MongoCampPaginationException("page must be greater then 0.")
    }

    val skip = (page - 1) * rows

    val listOfMetaData: List[Bson] = List(Map("$count" -> AggregationKeyMetaDataTotal))
    val listOfPaging: List[Bson]   = List(Map("$skip" -> skip), Map("$limit" -> rows))

    val pipeline =
      aggregationPipeline ++ List(
        Aggregates.facet(new Facet(AggregationKeyMetaData, listOfMetaData.asJava), new Facet(AggregationKeyData, listOfPaging.asJava))
      )

    val dbResponse = dao.Raw.findAggregated(pipeline, allowDiskUse).result(maxWait)

    val count: Long = dbResponse
      .get(AggregationKeyMetaData)
      .get
      .asArray()
      .asScala
      .headOption
      .map(v => v.asDocument().get(AggregationKeyMetaDataTotal).asNumber().longValue())
      .getOrElse(0)

    val allPages = Math.ceil(count.toDouble / rows).toInt
    val list     = dbResponse.get("data").get.asArray().asScala.map(_.asDocument()).map(bdoc => Document(bdoc))
    PaginationResult(list.toList, PaginationInfo(count, rows, page, allPages))
  }

  def countResult: Long = {
    val listOfMetaData: List[Bson] = List(Map("$count" -> AggregationKeyMetaDataTotal))
    val listOfPaging: List[Bson]   = List(Map("$skip" -> 0), Map("$limit" -> 1))

    val pipeline = aggregationPipeline ++ List(
      Aggregates.facet(new Facet(AggregationKeyMetaData, listOfMetaData.asJava), new Facet(AggregationKeyData, listOfPaging.asJava))
    )
    val dbResponse = dao.Raw.findAggregated(pipeline, allowDiskUse).result(maxWait)
    val count: Long = dbResponse
      .get(AggregationKeyMetaData)
      .get
      .asArray()
      .asScala
      .headOption
      .map(v => v.asDocument().get(AggregationKeyMetaDataTotal).asNumber().longValue())
      .getOrElse(0)

    count
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy