value slice不是play.api.libs.iteratee.Enumerator的成员

时间:2015-03-10 14:58:20

标签: scala cassandra-2.0 phantom-dsl

我正在编写基于https://github.com/websudos/phantom#partial-select-queries

中描述的“大型记录集的异步迭代器”的代码
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatter

import com.anomaly42.aml.dao.CassandraConnector
import com.websudos.phantom.CassandraTable
import com.websudos.phantom.Implicits._

object People extends People {
  def getPersonByUpdatedAt(from:String, to:String, start: Int, limit: Int) = {
    val dtf:DateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ");
    val fromDateTime = dtf.parseDateTime(from)
    val toDateTime = dtf.parseDateTime(to)

    People.select(_.updated_at, _.firstName).allowFiltering.where(_.updated_at gte fromDateTime).and(_.updated_at lte toDateTime).fetchEnumerator().slice(start, limit).collect
  }
}

我正在使用以下库依赖:

scalaVersion  := "2.11.6"
libraryDependencies ++= Seq(
  "com.websudos"        %%  "phantom-dsl"     % "1.5.4",
  many more...
)

但是我在编译时遇到以下错误:

value slice is not a member of play.api.libs.iteratee.Enumerator[(org.joda.time.DateTime, Option[String])]

我要做的是编写一个查询,每次调用getPersonByUpdatedAt()方法时,从'start'开始返回下一个'limit'结果数。

2 个答案:

答案 0 :(得分:3)

这里有很多实现细节需要解决。首先,如果您在分页后,可能有一种更简单的方法来实现简单范围查询而不是过滤数据。

看一下使用CLUSTERING ORDER,对ALLOW FILTERING的调用不应该在那里。此外,如果没有CLUSTERING ORDER默认的Murmur3分区程序实际上没有订购,那么您无法保证按照您编写的相同顺序检索数据。

这可能意味着你的分页根本不起作用。最后但并非最不重要的是,直接使用枚举器可能不是你想要的。

它们是异步的,所以你必须在未来内部映射才能得到一个切片,但除此之外,当像Spark一样加载一个整个表时,枚举器很有用,例如很多结果。

总结一下,在人员表中:

object id extends UUIDColumn(this) with PartitionKey[UUID]// doesn't have to be UUID
object start extends DateTimeColumn(this) with ClusteringOrder[DateTime] with Ascending
object end extends DateTimeColumn(this) with ClusteringOrder[DateTime] with Ascending

只需使用Scala集合库中的fetch()然后Seq.slice即可。上面假设你想要按升序分页,例如检索最早的第一个。

您还需要弄清楚实际的分区键是什么。如果同时更新2个用户,最糟糕的情况是丢失数据并结束FIFO队列,例如在给定时间的最后更新"胜出"。我上面使用了id,但这显然不是你需要的。

您可能需要有几个表格来存储人员,以便您可以覆盖所需的所有查询。

答案 1 :(得分:1)

你应该使用Play框架中的Iteratee和Enumerator。在您的情况下,您需要:

import com.websudos.phantom.iteratee.Iteratee

val enumerator =  People.select(_.updated_at, _.firstName).allowFiltering.where(_.updated_at gte fromDateTime).and(_.updated_at lte toDateTime).fetchEnumerator

val iteratee = Iteratee.slice[PeopleCaseClass](start, limit)

enumerator.run( iteratee ).map( _.foldLeft( List.empty[PeopleCaseClass] )( (l,e) => { e :: l } ))

希望这会有所帮助