关于集合包含和排序的 Phantom DSL 问题

Phantom DSL questions on set contains and sorting

我使用 Phantom DSL 编写了这个 scala 代码来查询 cassandra

  def getByGenreAndYear(genre: List[String], year: Int) : Future[Seq[Movie]] = {
    var criteria = select.where(_.genre contains genre.head)
    criteria = genre.tail.foldLeft(criteria){(accum, i) => accum.and(_.genre contains i)}
    criteria.and(_.year eqs year)
    criteria.allowFiltering().fetch()
  }

有效,但我有几个问题

查询集合是否包含值时。像我一样构建查询条件是否正确?基本上我对每个要检查的值都有一个 AND 子句。这能像

这样一次性完成吗
select.where(_.genre contains genreList)

我无法生成排序查询。当我尝试做

  def getByGenreAndYear(genre: List[String], year: Int) : Future[Seq[Movie]] = {
    var criteria = select.where(_.genre contains genre.head)
    criteria = genre.tail.foldLeft(criteria){(accum, i) => accum.and(_.genre contains i)}
    criteria.and(_.year eqs year)
    criteria.orderBy(_.year desc)
    criteria.allowFiltering().fetch()
  }

代码甚至无法编译

包含查询

您不能同时对多个值进行 contains 查询。您有几种方法可以实现上述目标。第一种是使用过滤并构建查询。

def getByGenreAndYear(genre: List[String], year: Int): Future[Seq[Movie]] = {
    val rootQuery = select.where(_.genre contains genre.head)
    genre.tail.foldLeft(rootQuery){ (accum, i) => accum.and(_.genre contains i)}
   .and(_.year eqs year)
   .orderBy(_.year desc)
   .allowFiltering().fetch()
  }

这就是您在此处所做的,除了幻象查询构建器是 不可变的 ,您执行的每个操作都将创建一个新的 Query 实例。这是有充分理由的。

另一种方法是对未来进行排序而不是在 Cassandra 中进行过滤,这并不总是非常可取。

def getByGenreAndYear(genre: List[String], year: Int): Future[Seq[Movie]] = {
  // This will create a future to query for a single value.
  val futures = genre.map(item => select.where(_.year eqs year).and(_.genre contains item).fetch())
  // This will sequence the entire set, produce a list of lists, flatten it and create an union, and deduplicate by set conversion granted you define the right `hashCode` method on the `Movie` class.
  Future.sequence(futures) map {
   // You could also probably get away with lists.flatten
   lists => lists.foldRight(Nil)((item, acc) => item ::: acc)).toSet
  }
}

目前无法在单个查询中针对多个值执行 CONTAINS 查询。你得到一个错误:

cql select * from marvis.expenses where tags contains ('food', 'office-food'); InvalidRequest: code=2200 [Invalid query] message="Invalid tuple type literal for value(tags) of type text"

然而这有效:

select * from marvis.expenses where tags contains 'food' and tags contains 'office-food' ALLOW FILTERING;

正在排序

实现排序需要CompoundComposite键,只能按clustering key部分排序列的,而不是 Partition key 部分。如果需要,请查看 this tutorial 了解有关 Cassandra 索引的更多详细信息。