
commonMain.com.algolia.search.model.response.ResponseSearch.kt Maven / Gradle / Ivy
package com.algolia.search.model.response
import com.algolia.search.ExperimentalAlgoliaClientAPI
import com.algolia.search.endpoint.EndpointSearch
import com.algolia.search.model.Attribute
import com.algolia.search.model.IndexName
import com.algolia.search.model.ObjectID
import com.algolia.search.model.QueryID
import com.algolia.search.model.analytics.ABTestID
import com.algolia.search.model.filter.FilterGroup
import com.algolia.search.model.insights.InsightsEvent
import com.algolia.search.model.rule.RenderingContent
import com.algolia.search.model.search.Cursor
import com.algolia.search.model.search.Explain
import com.algolia.search.model.search.Facet
import com.algolia.search.model.search.FacetStats
import com.algolia.search.model.search.Point
import com.algolia.search.model.search.Query
import com.algolia.search.model.search.RankingInfo
import com.algolia.search.model.search.RemoveWordIfNoResults
import com.algolia.search.model.settings.Settings
import com.algolia.search.serialize.KSerializerFacetMap
import com.algolia.search.serialize.KSerializerPoint
import com.algolia.search.serialize.internal.Json
import com.algolia.search.serialize.internal.JsonNonStrict
import com.algolia.search.serialize.internal.Key
import com.algolia.search.serialize.internal.asJsonInput
import com.algolia.search.serialize.internal.asJsonOutput
import com.algolia.search.serialize.internal.jsonObjectOrNull
import com.algolia.search.serialize.internal.jsonPrimitiveOrNull
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.floatOrNull
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonObject
@Serializable
public data class ResponseSearch(
/**
* The hits returned by the search. Hits are ordered according to the ranking or sorting of the index being queried.
* Hits are made of the schemaless JSON objects that you stored in the index.
*/
@SerialName(Key.Hits) val hitsOrNull: List? = null,
/**
* The number of hits matched by the query.
*/
@SerialName(Key.NbHits) val nbHitsOrNull: Int? = null,
/**
* Index of the current page (zero-based). See the [Query.page] search parameter.
* Not returned if you use offset/length for pagination.
*/
@SerialName(Key.Page) val pageOrNull: Int? = null,
/**
* The maximum number of hits returned per page. See the [Query.hitsPerPage] search parameter.
* Not returned if you use offset & length for pagination.
*/
@SerialName(Key.HitsPerPage) val hitsPerPageOrNull: Int? = null,
/**
* Alternative to [page] (zero-based). Is returned only when [Query.offset] [Query.length] is specified.
*/
@SerialName(Key.Offset) val offsetOrNull: Int? = null,
/**
* Alternative to [hitsPerPageOrNull] (zero-based). Is returned only when [Query.offset] [Query.length] is specified.
*/
@SerialName(Key.Length) val lengthOrNull: Int? = null,
/**
* Array of userData object. Only returned if at least one query rule containing a custom userData
* consequence was applied.
*/
@SerialName(Key.UserData) val userDataOrNull: List? = null,
/**
* The number of returned pages. Calculation is based on the total number of hits (nbHits) divided by the number of
* hits per page (hitsPerPage), rounded up to the nearest integer.
* Not returned if you use offset & length for pagination.
*/
@SerialName(Key.NbPages) val nbPagesOrNull: Int? = null,
/**
* Time the server took to process the request, in milliseconds. This does not include network time.
*/
@SerialName(Key.ProcessingTimeMS) val processingTimeMSOrNull: Long? = null,
/**
* Whether the nbHits is exhaustive (true) or approximate (false). An approximation is done when the query takes
* more than 50ms to be processed (this can happen when using complex filters on millions on records).
* See the related [discussion][https://www.algolia.com/doc/faq/index-configuration/my-facet-and-hit-counts-are-not-accurate/]
*/
@SerialName(Key.ExhaustiveNbHits) val exhaustiveNbHitsOrNull: Boolean? = null,
/**
* Whether the facet count is exhaustive (true) or approximate (false).
* See the related [discussion][https://www.algolia.com/doc/faq/index-configuration/my-facet-and-hit-counts-are-not-accurate/].
*/
@SerialName(Key.ExhaustiveFacetsCount) val exhaustiveFacetsCountOrNull: Boolean? = null,
/**
* An echo of the query text. See the [Query.query] search parameter.
*/
@SerialName(Key.Query) val queryOrNull: String? = null,
/**
* A markup text indicating which parts of the original query have been removed in order to retrieve a non-empty
* result set.
* The removed parts are surrounded by tags.
* Only returned when [Query.removeWordsIfNoResults] or [Settings.removeWordsIfNoResults] is set to
* [RemoveWordIfNoResults.LastWords] or [RemoveWordIfNoResults.FirstWords].
*/
@SerialName(Key.QueryAfterRemoval) val queryAfterRemovalOrNull: String? = null,
/**
* An url-encoded string of all [Query] parameters.
*/
@SerialName(Key.Params) val paramsOrNull: String? = null,
/**
* Used to return warnings about the query.
*/
@SerialName(Key.Message) val messageOrNull: String? = null,
/**
* The computed geo location.
* Only returned when [Query.aroundLatLngViaIP] or [Query.aroundLatLng] is set.
*/
@SerialName(Key.AroundLatLng) @Serializable(KSerializerPoint::class) val aroundLatLngOrNull: Point? = null,
/**
* The automatically computed radius. For legacy reasons, this parameter is a string and not an integer.
* Only returned for geo queries without an explicitly specified [Query.aroundRadius].
*/
@SerialName(Key.AutomaticRadius) val automaticRadiusOrNull: Float? = null,
/**
* Actual host name of the server that processed the request. Our DNS supports automatic failover and load
* balancing, so this may differ from the host name used in the request.
* Returned only if [Query.getRankingInfo] is set to true.
*/
@SerialName(Key.ServerUsed) val serverUsedOrNull: String? = null,
/**
* Index name used for the query. In case of A/B test, the index targeted isn’t always the index used by the query.
* Returned only if [Query.getRankingInfo] is set to true.
*/
@SerialName(Key.IndexUsed) val indexUsedOrNull: IndexName? = null,
/**
* In case of A/B test, reports the variant ID used. The variant ID is the position in the array of variants
* (starting at 1).
* Returned only if [Query.getRankingInfo] is set to true.
*/
@SerialName(Key.AbTestVariantID) val abTestVariantIDOrNull: Int? = null,
/**
* The query string that will be searched, after
* [normalization][https://www.algolia.com/doc/guides/managing-results/optimize-search-results/handling-natural-languages-nlp/in-depth/normalization/#what-is-normalization].
* Normalization includes removing stop words (if [Query.removeStopWords] or [Settings.removeStopWords] is enabled),
* and transforming portions of the query string into phrase queries
* (see [Query.advancedSyntax] or [Settings.advancedSyntax]).
* Returned only if [Query.getRankingInfo] is set to true.
*/
@SerialName(Key.ParsedQuery) val parsedQueryOrNull: String? = null,
/**
* A mapping of each facet name to the corresponding facet counts.
* Returned only if [Query.facets] is non-empty.
*/
@SerialName(Key.Facets) @Serializable(KSerializerFacetMap::class) val facetsOrNull: Map>? = null,
/**
* A mapping of each facet name to the corresponding facet counts for disjunctive facets.
* Returned only by the [EndpointSearch.advancedSearch] method.
* [Documentation][https://www.algolia.com/doc/guides/building-search-ui/going-further/backend-search/how-to/faceting/?language=kotlin#conjunctive-and-disjunctive-faceting]
*/
@SerialName(Key.DisjunctiveFacets) @Serializable(KSerializerFacetMap::class) val disjunctiveFacetsOrNull: Map>? = null,
/**
* Statistics for numerical facets.
* Returned only if [Query.facets] is non-empty and at least one of the returned facets contains numerical values.
*/
@SerialName(Key.Facets_Stats) val facetStatsOrNull: Map? = null,
/**
* Returned only by the [EndpointSearch.browse] method.
*/
@SerialName(Key.Cursor) val cursorOrNull: Cursor? = null,
/**
* Index name used for the query. In case of A/B test, the index targeted isn’t always the index used by the query.
* Returned only if [Query.getRankingInfo] is set to true.
*/
@SerialName(Key.Index) val indexNameOrNull: IndexName? = null,
@SerialName(Key.Processed) val processedOrNull: Boolean? = null,
/**
* Identifies the query uniquely. Can be used by [InsightsEvent].
*/
@SerialName(Key.QueryID) val queryIDOrNull: QueryID? = null,
/**
* A mapping of each facet name to the corresponding facet counts for hierarchical facets.
* Returned only by the [EndpointSearch.advancedSearch] method, only if a [FilterGroup.And.Hierarchical] is used.
*/
@SerialName(Key.HierarchicalFacets) val hierarchicalFacetsOrNull: Map>? = null,
/**
* Meta-information as to how the query was processed.
*/
@SerialName(Key.Explain) val explainOrNull: Explain? = null,
/**
* The rules applied to the query.
*/
@SerialName(Key.AppliedRules) val appliedRulesOrNull: List? = null,
/**
* Applied relevancy score in the virtual index [0-100].
*/
@SerialName(Key.AppliedRelevancyStrictness) val appliedRelevancyStrictnessOrNull: Int? = null,
/**
* Number of relevant hits to display in case of non-zero `relevancyStrictness` applied.
*/
@SerialName(Key.NbSortedHits) val nbSortedHitsOrNull: Int? = null,
/**
* Content defining how the search interface should be rendered.
*/
@SerialName(Key.RenderingContent) val renderingContentOrNull: RenderingContent? = null,
/**
* In case of A/B test, reports the ID of the A/B test used.
* Returned only if [Query.getRankingInfo] is set to true.
*/
@SerialName(Key.ABTestID) val abTestIDOrNull: ABTestID? = null
) : ResultSearch {
/**
* The hits returned by the search. Hits are ordered according to the ranking or sorting of the index being queried.
* Hits are made of the schemaless JSON objects that you stored in the index.
*
* @throws IllegalStateException if [hitsOrNull] is null
*/
public val hits: List
get() = checkNotNull(hitsOrNull)
/**
* The number of hits matched by the query.
*
* @@throws IllegalStateException if [nbHitsOrNull] is null
*/
public val nbHits: Int
get() = checkNotNull(nbHitsOrNull)
/**
* Index of the current page (zero-based). See the [Query.page] search parameter.
* Not returned if you use offset/length for pagination.
*
* @throws IllegalStateException if [pageOrNull] is null
*/
public val page: Int
get() = checkNotNull(pageOrNull)
/**
* The maximum number of hits returned per page. See the [Query.hitsPerPage] search parameter.
* Not returned if you use offset & length for pagination.
*
* @throws IllegalStateException if [hitsPerPage] is null
*/
public val hitsPerPage: Int
get() = checkNotNull(hitsPerPageOrNull)
/**
* Alternative to [hitsPerPageOrNull] (zero-based). Is returned only when [Query.offset] [Query.length] is specified.
*
* @throws IllegalStateException if [lengthOrNull] is null
*/
public val length: Int
get() = checkNotNull(lengthOrNull)
/**
* Alternative to [page] (zero-based). Is returned only when [Query.offset] [Query.length] is specified.
*
* @throws IllegalStateException if [offsetOrNull] is null
*/
public val offset: Int
get() = checkNotNull(offsetOrNull)
/**
* Array of userData object. Only returned if at least one query rule containing a custom userData
* consequence was applied.
*
* @throws IllegalStateException if [userDataOrNull] is null
*/
public val userData: List
get() = checkNotNull(userDataOrNull)
/**
* The number of returned pages. Calculation is based on the total number of hits (nbHits) divided by the number of
* hits per page (hitsPerPage), rounded up to the nearest integer.
* Not returned if you use offset & length for pagination.
*
* @throws IllegalStateException if [nbPagesOrNull] is null
*/
public val nbPages: Int
get() = checkNotNull(nbPagesOrNull)
/**
* Time the server took to process the request, in milliseconds. This does not include network time.
*
* @throws IllegalStateException if [processingTimeMSOrNull] is null
*/
public val processingTimeMS: Long
get() = checkNotNull(processingTimeMSOrNull)
/**
* Whether the nbHits is exhaustive (true) or approximate (false). An approximation is done when the query takes
* more than 50ms to be processed (this can happen when using complex filters on millions on records).
* See the related [discussion][https://www.algolia.com/doc/faq/index-configuration/my-facet-and-hit-counts-are-not-accurate/]
*
* @throws IllegalStateException if [exhaustiveNbHitsOrNull] is null
*/
public val exhaustiveNbHits: Boolean
get() = checkNotNull(exhaustiveNbHitsOrNull)
/**
* Whether the facet count is exhaustive (true) or approximate (false).
* See the related [discussion][https://www.algolia.com/doc/faq/index-configuration/my-facet-and-hit-counts-are-not-accurate/].
*
* @throws IllegalStateException if [exhaustiveFacetsCountOrNull] is null
*/
public val exhaustiveFacetsCount: Boolean
get() = checkNotNull(exhaustiveFacetsCountOrNull)
/**
* An echo of the query text. See the [Query.query] search parameter.
*
* @throws IllegalStateException if [queryOrNull] is null
*/
public val query: String
get() = checkNotNull(queryOrNull)
/**
* A markup text indicating which parts of the original query have been removed in order to retrieve a non-empty
* result set.
* The removed parts are surrounded by tags.
* Only returned when [Query.removeWordsIfNoResults] or [Settings.removeWordsIfNoResults] is set to
* [RemoveWordIfNoResults.LastWords] or [RemoveWordIfNoResults.FirstWords].
*
* @throws IllegalStateException if [queryAfterRemovalOrNull] is null
*/
public val queryAfterRemoval: String
get() = checkNotNull(queryAfterRemovalOrNull)
/**
* An url-encoded string of all [Query] parameters.
*
* @throws IllegalStateException if [paramsOrNull] is null
*/
public val params: String
get() = checkNotNull(paramsOrNull)
/**
* Used to return warnings about the query.
*
* @throws IllegalStateException if [messageOrNull] is null
*/
public val message: String
get() = checkNotNull(messageOrNull)
/**
* The computed geo location.
* Only returned when [Query.aroundLatLngViaIP] or [Query.aroundLatLng] is set.
*
* @throws IllegalStateException if [aroundLatLngOrNull] is null
*/
public val aroundLatLng: Point
get() = checkNotNull(aroundLatLngOrNull)
/**
* The automatically computed radius. For legacy reasons, this parameter is a string and not an integer.
* Only returned for geo queries without an explicitly specified [Query.aroundRadius].
*
* @throws IllegalStateException if [automaticRadiusOrNull] is null
*/
public val automaticRadius: Float
get() = checkNotNull(automaticRadiusOrNull)
/**
* Actual host name of the server that processed the request. Our DNS supports automatic failover and load
* balancing, so this may differ from the host name used in the request.
* Returned only if [Query.getRankingInfo] is set to true.
*
* @throws IllegalStateException if [serverUsedOrNull] is null
*/
public val serverUsed: String
get() = checkNotNull(serverUsedOrNull)
/**
* Index name used for the query. In case of A/B test, the index targeted isn’t always the index used by the query.
* Returned only if [Query.getRankingInfo] is set to true.
*
* @throws IllegalStateException if [indexUsedOrNull] is null
*/
public val indexUsed: IndexName
get() = checkNotNull(indexUsedOrNull)
/**
* In case of A/B test, reports the variant ID used. The variant ID is the position in the array of variants
* (starting at 1).
* Returned only if [Query.getRankingInfo] is set to true.
*
* @throws IllegalStateException if [abTestVariantIDOrNull] is null
*/
public val abTestVariantID: Int
get() = checkNotNull(abTestVariantIDOrNull)
/**
* The query string that will be searched, after
* [normalization][https://www.algolia.com/doc/guides/managing-results/optimize-search-results/handling-natural-languages-nlp/in-depth/normalization/#what-is-normalization].
* Normalization includes removing stop words (if [Query.removeStopWords] or [Settings.removeStopWords] is enabled),
* and transforming portions of the query string into phrase queries
* (see [Query.advancedSyntax] or [Settings.advancedSyntax]).
* Returned only if [Query.getRankingInfo] is set to true.
*
* @throws IllegalStateException if [parsedQueryOrNull] is null
*/
public val parsedQuery: String
get() = checkNotNull(parsedQueryOrNull)
/**
* A mapping of each facet name to the corresponding facet counts.
* Returned only if [Query.facets] is non-empty.
*
* @throws IllegalStateException if [facetsOrNull] is null
*/
public val facets: Map>
get() = checkNotNull(facetsOrNull)
/**
* A mapping of each facet name to the corresponding facet counts for disjunctive facets.
* Returned only by the [EndpointSearch.advancedSearch] method.
* [Documentation][https://www.algolia.com/doc/guides/building-search-ui/going-further/backend-search/how-to/faceting/?language=kotlin#conjunctive-and-disjunctive-faceting]
*
* @throws IllegalStateException if [disjunctiveFacetsOrNull] is null
*/
public val disjunctiveFacets: Map>
get() = checkNotNull(disjunctiveFacetsOrNull)
/**
* Statistics for numerical facets.
* Returned only if [Query.facets] is non-empty and at least one of the returned facets contains numerical values.
*
* @throws IllegalStateException if [facetStatsOrNull] is null
*/
public val facetStats: Map
get() = checkNotNull(facetStatsOrNull)
/**
* Returned only by the [EndpointSearch.browse] method.
*
* @throws IllegalStateException if [cursorOrNull] is null
*/
public val cursor: Cursor
get() = checkNotNull(cursorOrNull)
/**
* Index name used for the query. In case of A/B test, the index targeted isn’t always the index used by the query.
* Returned only if [Query.getRankingInfo] is set to true.
*
* @throws IllegalStateException if [indexNameOrNull] is null
*/
public val indexName: IndexName
get() = checkNotNull(indexNameOrNull)
public val processed: Boolean
get() = checkNotNull(processedOrNull)
/**
* Identifies the query uniquely. Can be used by [InsightsEvent].
*
* @throws IllegalStateException if [queryIDOrNull] is null
*/
public val queryID: QueryID
get() = checkNotNull(queryIDOrNull)
/**
* A mapping of each facet name to the corresponding facet counts for hierarchical facets.
* Returned only by the [EndpointSearch.advancedSearch] method, only if a [FilterGroup.And.Hierarchical] is used.
*
* @throws IllegalStateException if [hierarchicalFacetsOrNull] is null
*/
public val hierarchicalFacets: Map>
get() = checkNotNull(hierarchicalFacetsOrNull)
/**
* Meta-information as to how the query was processed.
*
* @throws IllegalStateException if [explainOrNull] is null
*/
public val explain: Explain
get() = checkNotNull(explainOrNull)
/**
* The rules applied to the query.
*
* @throws IllegalStateException if [appliedRulesOrNull] is null
*/
public val appliedRules: List
get() = checkNotNull(appliedRulesOrNull)
/**
* Applied relevancy score in the virtual index [0-100].
*
* @throws IllegalStateException if [appliedRelevancyStrictnessOrNull] is null
*/
public val appliedRelevancyStrictness: Int
get() = requireNotNull(appliedRelevancyStrictnessOrNull)
/**
* Number of relevant hits to display in case of non-zero `relevancyStrictness` applied.
*
* @throws IllegalStateException if [nbSortedHitsOrNull] is null
*/
public val nbSortedHits: Int
get() = requireNotNull(nbSortedHitsOrNull)
/**
* Content defining how the search interface should be rendered.
*
* @throws IllegalStateException if [renderingContentOrNull] is null
*/
public val renderingContent: RenderingContent
get() = requireNotNull(renderingContentOrNull)
/**
* In case of A/B test, reports the ID of the A/B test used.
* Returned only if [Query.getRankingInfo] is set to true.
*
* @throws IllegalStateException if [abTestIDOrNull] is null.
*/
public val abTestID: ABTestID
get() = checkNotNull(abTestIDOrNull)
/**
* Returns the position (0-based) within the [hits] result list of the record matching against the given [objectID].
* If the [objectID] is not found, -1 is returned.
*/
public fun getObjectPosition(objectID: ObjectID): Int {
return hits.indexOfFirst { it.json["objectID"]?.jsonPrimitiveOrNull?.content == objectID.raw }
}
/**
* A Hit returned by the search.
*/
@Serializable(Hit.Companion::class)
public data class Hit(
val json: JsonObject,
) : Map by json {
public val distinctSeqIDOrNull: Int? = json[Key._DistinctSeqID]?.jsonPrimitiveOrNull?.int
public val rankingInfoOrNull: RankingInfo? = json[Key._RankingInfo]?.jsonObjectOrNull?.let {
JsonNonStrict.decodeFromJsonElement(RankingInfo.serializer(), it)
}
public val highlightResultOrNull: JsonObject? = json[Key._HighlightResult]?.jsonObjectOrNull
public val snippetResultOrNull: JsonObject? = json[Key._SnippetResult]?.jsonObjectOrNull
@ExperimentalAlgoliaClientAPI
public val answerOrNull: Answer? = json[Key._Answer]?.jsonObjectOrNull?.let {
JsonNonStrict.decodeFromJsonElement(Answer.serializer(), it)
}
public val scoreOrNull: Float? = json[Key._Score]?.jsonPrimitiveOrNull?.floatOrNull
public val rankingInfo: RankingInfo
get() = checkNotNull(rankingInfoOrNull)
public val distinctSeqID: Int
get() = checkNotNull(distinctSeqIDOrNull)
public val highlightResult: JsonObject
get() = checkNotNull(highlightResultOrNull)
public val snippetResult: JsonObject
get() = checkNotNull(snippetResultOrNull)
@ExperimentalAlgoliaClientAPI
public val answer: Answer
get() = checkNotNull(answerOrNull)
public val score: Float
get() = checkNotNull(scoreOrNull)
/**
* Deserialize the value of an [Attribute] to [T].
*/
public fun getValue(serializer: KSerializer, attribute: Attribute): T {
return Json.decodeFromJsonElement(serializer, json.getValue(attribute.raw))
}
/**
* Deserialize the entire [json] to [T].
*/
public fun deserialize(deserializer: DeserializationStrategy): T {
return JsonNonStrict.decodeFromJsonElement(deserializer, json)
}
@OptIn(ExperimentalSerializationApi::class)
@Serializer(Hit::class)
public companion object : KSerializer {
override fun deserialize(decoder: Decoder): Hit {
return Hit(decoder.asJsonInput().jsonObject)
}
override fun serialize(encoder: Encoder, value: Hit) {
encoder.asJsonOutput().encodeJsonElement(value.json)
}
}
}
@Serializable
public data class Answer(
@SerialName(Key.Extract) val extract: String,
@SerialName(Key.Score) val score: Double,
@SerialName(Key.ExtractAttribute) val extractAttribute: Attribute,
)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy