1

我已经使用 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()
  }

代码甚至无法编译

4

1 回答 1

1

包含查询

您不能同时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;

排序

要实现排序,需要一个Compound或者Composite key,并且只能按clustering key列的部分排序,不能按Partition key部分排序。如果需要,请查看本教程以获取有关 Cassandra 索引的更多详细信息。

于 2016-03-07T10:17:12.863 回答