scala 为什么“LIKE”,“Contain”,“REGIX”运算符在phentom-dsl库(scylladb)中不起作用?

ggazkfy8  于 2023-05-22  发布在  Scala
关注(0)|答案(2)|浏览(175)

我使用scala语言和scylladb数据库使用phantom-dsl库。
我想用方法从scylladb中得到以city为基础的学生数据

override def getStudnetByCity(city: String): Future[List[Student]] = {
studentDB.Student
   .select
   .where(_.city eqs city)
   .fetch()
}

上面的代码运行良好。
现在,我想通过仅使用给定代码搜索JERSEY来获得来自JERSEY以及NEW JERSEYWEST NEW JERSEY的所有学生

override def getStudnetByCity(city: String): Future[List[Student]] = {
studentDB.Student
   .select
   .where(_.city like s"%$city%")
   .fetch()
}

但在like处出现错误
错误:无法解析符号
我尝试的:我导入库:

import com.outworkers.phantom.builder.syntax.CQLSyntax.Operators.like

但什么也没发生,仍然得到相同的错误。
这是我大楼。

ThisBuild / scalaVersion := "2.13.1"

libraryDependencies ++= Seq(
  "com.outworkers" %% "phantom-dsl" % "2.59.0"
)

是phontom不支持还是有其他方法?

xwbd5t1u

xwbd5t1u1#

ScyllaDB支持LIKE操作符,与您尝试使用的操作符完全相同,但仅限于filteringselects(使用ALLOW FILTERING),这意味着select读取所有数据(单个分区或整个数据库)并检查每行是否与您的LIKE操作符匹配。
显然,对于许多用例来说,这样的“过滤”是低效和不合适的,您希望提前准备一个索引以使其高效。Gaston的回答建议你应该使用SASI,Cassandra的高级文本搜索二级索引,但不幸的是,这在ScyllaDB(https://github.com/scylladb/scylladb/issues/2203)中从未实现过,现在这个功能也从Cassandra中删除了,它永远不会在ScyllaDB中实现。
ScyllaDB还有另一个建议,也没有完成,添加索引支持高效的LIKE操作,而不添加完全通用的索引机制:https://github.com/scylladb/scylladb/issues/6458。但是这个也还没有。
但是,在现有的ScyllaDB中,您可以在应用程序中执行以下操作:你可以自己进行所谓的“lemmatization”:代替(或除了)存储字符串"WESTERN NEW JERSEY"存储,在列表列中类似["western", "new", "jersey"]。然后,您可以在此列表列上添加二级索引(ScyllaDB自2022年8月起支持此索引),然后您可以高效地搜索“jersey”并获得相关结果。
我不知道,但是,如何做到这一点与幻影dsl任何。我猜这个框架只是简单地将各种Scala对象转换为CQL命令,所以你只需要弄清楚传递你想要传递的CQL命令的正确方法。

dzhpxtsq

dzhpxtsq2#

编辑:
我写了一个很详细的一步一步的“解决方案”。问题是,这个问题是针对ScyllaDB的,由于ScyllaDB doesn't support SASI Index,我的方法只适用于Cassandra。Cassandra中的SASI索引也是实验性的,它将在v5中被弃用,并在v6中被删除。
@NadavHar'El的答案是正确的。我将添加一个示例,说明如何使用phantom遵循他的建议。

import com.outworkers.phantom.dsl._

abstract class Students extends Table[Students, Student] {
  object id extends UUIDColumn with PartitionKey
  object name extends StringColumn
  object email extends StringColumn
  object city extends ListColumn[String] with Index

  def cityLike(city: String) = {
    select.where(student => student.city eqs city).fetch()
  }
}

老答案:(使用Cassandra的一个实验性功能,该功能将被弃用)
为了能够做到这一点,phantom允许您添加SASI Index support。根据您提供的代码,您的表定义应该类似于

import com.outworkers.phantom.dsl._

case class Student(
  id: UUID,
  name: String,
  email: String,
  city: String
)

abstract class Students extends Table[Students, Student] {
  object id extends UUIDColumn with PartitionKey
  object name extends StringColumn
  object email extends StringColumn
  object city extends StringColumn // the column you want to filter using `LIKE` operator

  def cityLike(city: String) = {
    select.where(student => student.city eqs(city)).fetch()
  }
}

如文档中模式部分所述:
有两种模式专门针对文本列,即Mode.PrefixMode.Contains。通过使用这些模式,您将能够使用like运算符执行特定于文本的查询。
下一步是为要过滤的列添加SASI支持

import com.outworkers.phantom.dsl._

abstract class Students extends Table[Students, Student] {
  object id extends UUIDColumn with PartitionKey
  object name extends StringColumn
  object email extends StringColumn
  object city extends StringColumn with SASIIndex[Mode.Contains] { // adding SASI Index using MODE.Contains
    override def analyzer: Analyzer[Mode.Contains] = // the analyzer must be override based on your needs
      Analyzer.NonTokenizingAnalyzer[Mode.Contains]().normalizeLowercase(true)
  }

  def cityLike(city: String) = {
    // once you added the SASI index to the column, you can filter
    // the column using the operator `LIKE`
    select.where(student => student.city like contains(city)).fetch()
  }
}

SASI索引必须存在。

  • 可以使用CQL创建SASI索引
CREATE CUSTOM INDEX ON students (city) 
                 USING 'org.apache.cassandra.index.sasi.SASIIndex'
                  WITH OPTIONS = {
                      'analyzer_class': 'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer',
                      'case_sensitive': 'false'
                  };

在你的一些应用程序中,你会看到类似于

class AppDatabase(override val connector: CassandraConnection)
    extends Database[AppDatabase](connector) {
  object students extends Students with Connector

  def createStudentsTable = students.create.ifNotExists()
}
  • 或使用scylla java驱动程序创建自定义索引

要做到这一点,您必须添加正确的依赖项

"com.scylladb" % "java-driver-query-builder" % "4.15.0.0"

然后你可以做以下的事情

import com.datastax.oss.driver.api.querybuilder.SchemaBuilder.createIndex

object CustomIndex {
  val citySasiIndex = createIndex()
    .usingSASI()
    .onTable("students")
    .andColumn("city")
    .withSASIOptions(
      ImmutableMap.of("mode", "CONTAINS", "tokenization_locale", "en")
    )
}

回到你最初的问题phantom supports like operator?,答案是Yes。做这件事是可能的。您应该记住,您必须执行一些额外的步骤,并评估使用一种或其他类型的索引之间的权衡。有关SASI Index的更多信息,我在stackoverflow中找到了以下其他帖子:

相关问题