以下是代码:
import java.util.{Calendar, Date, GregorianCalendar}
import com.mongodb.casbah.Imports._
import com.mongodb.casbah.commons.conversions.scala._
case class Quota(date: Date, used: Int)
object MongoDateDemo extends App {
val client = InsertUsers.getClient
val db = client("github")
val quota = db("quota")
val rand = scala.util.Random
// quota.drop()
// (1 to 100).foreach { _ =>
// quota += DBObject("date" -> new Date(), "used" -> rand.nextInt(10))
// Thread.sleep(1000)
// }
val minuteInMilliseconds = 60 * 1000
def thresholdDate(minute: Int) = new Date(new Date() .getTime - minuteInMilliseconds * minute) // since a minute ago
val fields = DBObject("_id" -> 0, "used" -> 1)
val x = quota.find("date" $gte thresholdDate(28), fields).collect {
case x if x.getAs[Int]("used").isDefined => x.getAs[Int]("used").get
}
println(x.toList.sum)
// val y = x.map {
// case dbo: DBObject => Quota(dbo.getAs[Date]("date").getOrElse(new Date(0)), dbo.getAs[Int]("used").getOrElse(0))
// }
}
它正在从一个集合中读取文档,并过滤掉那些没有使用过的文档"定义,然后总结数字。
x.getAs[Int]("used")
部分是重复计算,我该如何避免呢?
答案 0 :(得分:3)
Scala程序员并不多,但是flatMap
的用途是什么?
quota
.find("date" $gte thresholdDate(38), fields)
.flatMap(_.getAs[Int]("used").toList)
答案 1 :(得分:0)
由于这是不可避免的,我必须分两步完成,映射到Option
然后收集。我使用了view
方法,因此集合不会遍历两次:
import java.util.{Calendar, Date, GregorianCalendar}
import com.mongodb.casbah.Imports._
import com.mongodb.casbah.commons.conversions.scala._
case class Quota(date: Date, used: Int)
object MongoDateDemo extends App {
val client = InsertUsers.getClient
val db = client("github")
val quota = db("quota")
val rand = scala.util.Random
// quota.drop()
// (1 to 100).foreach { _ =>
// quota += DBObject("date" -> new Date(), "used" -> rand.nextInt(10))
// Thread.sleep(1000)
// }
val minuteInMilliseconds = 60 * 1000
def thresholdDate(minute: Int) = new Date(new Date() .getTime - minuteInMilliseconds * minute) // since a minute ago
val fields = DBObject("_id" -> 0, "used" -> 1)
val usedNumbers = quota.find("date" $gte thresholdDate(38), fields).toList.view.map {
_.getAs[Int]("used")
}.collect {
case Some(i) => i
}.force
println(usedNumbers.sum)
// val y = x.map {
// case dbo: DBObject => Quota(dbo.getAs[Date]("date").getOrElse(new Date(0)), dbo.getAs[Int]("used").getOrElse(0))
// }
}
答案 2 :(得分:0)
假设getAs
返回一个选项,这应该可以达到你想要的效果:
val x = quota.find("date" $gte thresholdDate(28), fields).flatMap { _.getAs[Int]("used") }
这类似于这样做:
scala> List(Some(1), Some(2), None, Some(4)).flatMap(x => x)
res: List[Int] = List(1, 2, 4)
或者这个:
scala> (1 to 20).flatMap(x => if(x%2 == 0) Some(x) else None)
res: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)