EDIT:
I wrote a well detailed step by step "solution". The problem is that the question was for ScyllaDB and my approach will only work for Cassandra due to ScyllaDB doesn't support SASI Index. Also SASI index in Cassandra was experimental, it will be deprecated in v5 and removed in v6.
@NadavHar'El answer is the right one for this case. I will just add an example of how to follow his suggestion using 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()
}
}
OLD ANSWER: (Using an experimental feature from Cassandra that will be deprecated)
To be able to do that, phantom lets you add SASI Index support. Based on the code you provided, your table definition should be something like
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()
}
}
As it says in the docs in the Modes section:
There are two modes directed specifically at text columns, namely
Mode.Prefix
and Mode.Contains
. By using these modes, you will be able
to perform text specific queries using the like
operator.
The next step you have to do is add the SASI support for the column you want to filter
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()
}
}
The SASI index must exist.
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'
};
In some of your app you will have something like
class AppDatabase(override val connector: CassandraConnection)
extends Database[AppDatabase](connector) {
object students extends Students with Connector
def createStudentsTable = students.create.ifNotExists()
}
to be able to do that you have to add the correct dependency
"com.scylladb" % "java-driver-query-builder" % "4.15.0.0"
and then you can do the following
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")
)
}
backing to your initial question phantom supports like operator?
, the answer is Yes
. It is possible to do it. You should have in mind that you have to do some extra steps and evaluate the trade-offs between using one or other type of indexes. For further information about SASI Index, I've found this other posts in stackoverflow: