search Query
Returns a Flow which can be collected to execute a Full-Text Search query and process the results.
The returned Flow is cold, meaning the query is not executed unless the Flow is collected. If you collect the flow multiple times, the query is executed each time.
The extension function Flow<SearchFlowItem>.execute()
may be used when the results are known to fit in memory. It simply collects the flow into a SearchResult.
For larger query results, prefer the streaming version which takes a lambda to invoke when each row is received from the server: Flow<SearchFlowItem>.execute { row -> ... }
.
Samples
import com.couchbase.client.kotlin.Cluster
import com.couchbase.client.kotlin.search.Highlight
import com.couchbase.client.kotlin.search.NumericRange
import com.couchbase.client.kotlin.search.SearchFacet
import com.couchbase.client.kotlin.search.SearchQuery
import com.couchbase.client.kotlin.search.SearchResult
import com.couchbase.client.kotlin.search.SearchSort
import com.couchbase.client.kotlin.search.SearchSort.Companion.byField
import com.couchbase.client.kotlin.search.SearchSort.Companion.byId
import com.couchbase.client.kotlin.search.execute
fun main() {
//sampleStart
// A simple search query against the "travel-sample" sample bucket.
// Requires the "description" field to be indexed (stored).
val result = cluster.searchQuery(
indexName = "travel-sample-index-hotel-description",
fields = listOf("*"), // return all stored fields
query = SearchQuery.match(
match = "beautiful", // look for this term
field = "description", // limit the query to this field
),
highlight = Highlight.html(), // return matching fragments
).execute()
checkSearchQueryResultForPartialFailure(result) // see other sample
println(result.metadata)
result.rows.forEach { row ->
println(row.id)
println(row.score)
println(row.locations)
println(row.fragments)
println(row.fieldsAs<Map<String, Any?>>())
println()
}
//sampleEnd
}
import com.couchbase.client.kotlin.Cluster
import com.couchbase.client.kotlin.search.Highlight
import com.couchbase.client.kotlin.search.NumericRange
import com.couchbase.client.kotlin.search.SearchFacet
import com.couchbase.client.kotlin.search.SearchQuery
import com.couchbase.client.kotlin.search.SearchResult
import com.couchbase.client.kotlin.search.SearchSort
import com.couchbase.client.kotlin.search.SearchSort.Companion.byField
import com.couchbase.client.kotlin.search.SearchSort.Companion.byId
import com.couchbase.client.kotlin.search.execute
fun main() {
//sampleStart
// Checking a SearchResult for partial failure
val errors = searchResult.metadata.errors
val metrics = searchResult.metadata.metrics
if (errors.isNotEmpty()) {
if (metrics.failedPartitions == metrics.totalPartitions)
throw RuntimeException("Total failure. Errors: $errors")
// Proceed with partial results (or fail if you want)
println("Partial success. Errors: $errors")
}
//sampleEnd
}
import com.couchbase.client.kotlin.Cluster
import com.couchbase.client.kotlin.search.Highlight
import com.couchbase.client.kotlin.search.NumericRange
import com.couchbase.client.kotlin.search.SearchFacet
import com.couchbase.client.kotlin.search.SearchQuery
import com.couchbase.client.kotlin.search.SearchResult
import com.couchbase.client.kotlin.search.SearchSort
import com.couchbase.client.kotlin.search.SearchSort.Companion.byField
import com.couchbase.client.kotlin.search.SearchSort.Companion.byId
import com.couchbase.client.kotlin.search.execute
fun main() {
//sampleStart
// Searching with facets.
// Assumes the "beer-sample" sample bucket is installed,
// with a search index named "beer-search" where
// "abv" and "category" are indexed as stored fields.
// Count results that fall into these "alcohol by volume" ranges.
// Optionally assign names to the ranges.
val low = NumericRange.bounds(min = 0, max = 3.5, name = "low")
val high = NumericRange.lowerBound(3.5, name = "high")
val abv = SearchFacet.numeric(
field = "abv",
ranges = listOf(low, high),
name = "Alcohol by volume",
)
// Find the 5 most frequent values in the "category" field.
val beerType = SearchFacet.term("category", size = 5)
val result = cluster.searchQuery(
indexName = "beer-search",
query = SearchQuery.matchAll(),
facets = listOf(abv, beerType),
).execute()
// Print all facet results. Results do not include empty facets
// or ranges. Categories are ordered by size, descending.
result.facets.forEach { facet ->
println(facet.name)
facet.categories.forEach { println(" $it") }
facet.other.let { if (it > 0) println(" <other> ($it)") }
println()
}
// Alternatively, print results for a specific facet:
val abvResult = result[abv]
if (abvResult == null) {
println("No search results matched any of the 'abv' facet ranges.")
} else {
println("Alcohol by volume (again)")
println(" low (${abvResult[low]?.count ?: 0})")
println(" high (${abvResult[high]?.count ?: 0})")
println()
}
//sampleEnd
}
Parameters
Index to search.
Condition a document must match in order to be included in the search results.
Specifies which rows of the search result to return.
Number of rows to return (page size).
Specifies how the results should be sorted. For tiered sort (sort by X then by Y) see SearchSort.then.
Stored fields to include in the result rows, or listOf("*")
to include all stored fields.
Specifies the facets to include in the search results. A facet counts the number of documents in the full, unpaginated search results that meet certain criteria. Facet results may be retrieved from either SearchResult or SearchMetadata, whichever is more convenient.
Specifies whether to include fragments of text with the matching search term highlighted. If highlighting is requested, the result also includes location information for matched terms.
If true, triggers the inclusion of location information for matched terms. If highlighting is requested, locations are always included and this parameter has no effect.
The scoring algorithm to use.
If true, SearchRow.explanation holds the bytes of a JSON Object describing how the score was calculated.
If not empty, only search within the named collections. Requires an index defined on a non-default scope containing the collections.
Specifies whether to wait for the index to catch up with the latest versions of certain documents. The default (unbounded) is fast, but means the results might not reflect the latest document mutations.
Default serializer to use for SearchRow.fieldsAs. If not specified, defaults to the cluster environment's default serializer.
The keys and values in this map are added to the query specification JSON. This is an "escape hatch" for sending arguments supported by Couchbase Server, but not by this version of the SDK.