| name | search-scala | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| summary | Couchbase Full-Text Search, vector search, hybrid search, and geospatial search for Scala | ||||||||||||||||||||||||||
| description | Couchbase Full-Text Search, vector search, hybrid search, and geospatial search for Scala | ||||||||||||||||||||||||||
| compatibility | Scala SDK 1.x. Vector search requires Couchbase Server 7.6+. | ||||||||||||||||||||||||||
| metadata |
|
Create an FTS index before running text or vector queries. Use the templates as a starting point:
- FTS index: templates/fts-index-basic.json
- Vector index: templates/vector-index.json
See shared/server/search-concepts.md for setup instructions.
import com.couchbase.client.scala.search.{SearchOptions, SearchScanConsistency}
import com.couchbase.client.scala.search.queries.{MatchQuery, SearchQuery}
import com.couchbase.client.scala.search.result.{SearchResult, SearchRow}
import com.couchbase.client.scala.search.vector.{SearchRequest, VectorQuery, VectorSearch}
import com.couchbase.client.scala.kv.MutationState
import scala.util.{Success, Failure}val result = cluster.searchQuery(
"travel-sample-index-hotel-description",
MatchQuery("swanky"),
SearchOptions().limit(10)
)
result match {
case Success(res) =>
res.rows.foreach(row => println(s"id=${row.id} score=${row.score}"))
println(s"total=${res.metaData.metrics.totalRows}")
case Failure(err) => println(s"Error: $err")
}val scope = cluster.bucket("travel-sample").scope("inventory")
scope.searchQuery(
"my-scoped-index",
MatchQuery("ocean view"),
SearchOptions().limit(5)
) match {
case Success(res) => res.rows.foreach(row => println(row.id))
case Failure(err) => println(s"Error: $err")
}import com.couchbase.client.scala.search.queries._
// Term — exact token match
TermQuery("airline")
// Prefix
PrefixQuery("air")
// Boolean — AND/OR/NOT
BooleanQuery()
.must(MatchQuery("hotel"))
.mustNot(TermQuery("hostel"))
// Numeric range
NumericRangeQuery().min(3.0).max(5.0)
// Date range
DateRangeQuery().start("2020-01-01").end("2024-12-31")val queryVector: Array[Float] = Array(0.1f, 0.2f /*, ... 1536 dims */)
val request = SearchRequest.create(VectorSearch.create(
VectorQuery("embedding_field", queryVector).numCandidates(3)
))
cluster.search("my-vector-index", request, SearchOptions().limit(5)) match {
case Success(res) =>
res.rows.foreach(row => println(s"id=${row.id} score=${row.score}"))
case Failure(err) => println(s"Error: $err")
}val queryVector: Array[Float] = Array(0.1f, 0.2f /*, ... */)
val request = SearchRequest.create(MatchQuery("ocean view"))
.vectorSearch(VectorSearch.create(
VectorQuery("embedding_field", queryVector).numCandidates(3)
))
cluster.search("my-hybrid-index", request, SearchOptions().limit(10))import com.couchbase.client.scala.search.queries.GeoDistanceQuery
// Within 10km of a point
cluster.searchQuery(
"hotel-geo",
GeoDistanceQuery(37.7749, -122.4194, "10km").field("geo"),
SearchOptions().limit(20).fields("name", "geo")
) match {
case Success(result) => result.rows.foreach(row => println(row.id))
case Failure(err) => println(s"Search failed: $err")
}The geo field must be indexed as type: geopoint. Document format: {"geo": {"lat": 37.7749, "lon": -122.4194}}.
val insertResult = collection.insert(
"hotel::new",
JsonObject("name" -> "Hotel California", "desc" -> "Such a lonely place")
).get
val ms = MutationState(Seq(insertResult.mutationToken.get))
cluster.searchQuery(
"travel-sample-index-hotel-description",
MatchQuery("lonely"),
SearchOptions()
.limit(5)
.scanConsistency(SearchScanConsistency.ConsistentWith(ms))
)result match {
case Success(res) =>
res.rows.foreach { row =>
println(s"id=${row.id}")
println(s"score=${row.score}")
row.fields.foreach(f => println(s"fields=$f"))
}
val metrics = res.metaData.metrics
println(s"total=${metrics.totalRows} took=${metrics.took}")
case Failure(err) => println(s"Error: $err")
}Shared concepts: shared/server/search-concepts.md — prerequisites, hybrid search, RYOW, pagination, query types.