关于集合包含和排序的 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;
正在排序
实现排序需要Compound或Composite键,只能按clustering key
部分排序列的,而不是 Partition key 部分。如果需要,请查看 this tutorial 了解有关 Cassandra 索引的更多详细信息。
我使用 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;
正在排序
实现排序需要Compound或Composite键,只能按clustering key
部分排序列的,而不是 Partition key 部分。如果需要,请查看 this tutorial 了解有关 Cassandra 索引的更多详细信息。