Skip to content

Commit 5b61cae

Browse files
committed
fix(search): introduce new exhaustive object
1 parent 68a6d09 commit 5b61cae

File tree

14 files changed

+117
-5
lines changed

14 files changed

+117
-5
lines changed

client/src/commonMain/kotlin/com/algolia/search/dsl/advanced/DSLResponseFields.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class DSLResponseFields(
1717
public val AroundLatLng: ResponseFields.AroundLatLng = ResponseFields.AroundLatLng
1818
public val AutomaticRadius: ResponseFields.AutomaticRadius = ResponseFields.AutomaticRadius
1919
public val ExhaustiveFacetsCount: ResponseFields.ExhaustiveFacetsCount = ResponseFields.ExhaustiveFacetsCount
20+
public val Exhaustive: ResponseFields.Exhaustive = ResponseFields.Exhaustive
2021
public val Facets: ResponseFields.Facets = ResponseFields.Facets
2122
public val FacetsStats: ResponseFields.FacetsStats = ResponseFields.FacetsStats
2223
public val Hits: ResponseFields.Hits = ResponseFields.Hits

client/src/commonMain/kotlin/com/algolia/search/endpoint/internal/EndpointSearch.kt

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ import com.algolia.search.model.response.ResponseHitWithPosition
1717
import com.algolia.search.model.response.ResponseSearch
1818
import com.algolia.search.model.response.ResponseSearchForFacets
1919
import com.algolia.search.model.response.ResponseSearches
20-
import com.algolia.search.model.search.Cursor
21-
import com.algolia.search.model.search.Facet
22-
import com.algolia.search.model.search.FacetStats
23-
import com.algolia.search.model.search.Query
20+
import com.algolia.search.model.search.*
2421
import com.algolia.search.serialize.internal.JsonNoDefaults
2522
import com.algolia.search.serialize.internal.Key
2623
import com.algolia.search.serialize.internal.merge
@@ -148,6 +145,28 @@ internal class EndpointSearchImpl(
148145
}
149146
}
150147

148+
private fun List<ResponseSearch>.aggregateExhaustive(): Exhaustive? {
149+
val exhaustive: Exhaustive? = null
150+
151+
return fold(exhaustive) { acc, cur ->
152+
if (cur.exhaustiveOrNull == null) {
153+
return@fold acc
154+
}
155+
156+
if (acc == null) {
157+
return@fold cur.exhaustiveOrNull
158+
}
159+
160+
return@fold Exhaustive(
161+
facetsCount = if (cur.exhaustiveOrNull.facetsCount == null && acc.facetsCount == null) null else cur.exhaustiveOrNull.facetsCount == true && acc.facetsCount == true,
162+
facetValues = if (cur.exhaustiveOrNull.facetValues == null && acc.facetValues == null) null else cur.exhaustiveOrNull.facetValues == true && acc.facetValues == true,
163+
nbHits = cur.exhaustiveOrNull.nbHits && acc.nbHits,
164+
rulesMatch = if (cur.exhaustiveOrNull.rulesMatch == null && acc.rulesMatch == null) null else cur.exhaustiveOrNull.rulesMatch == true && acc.rulesMatch == true,
165+
typo = if (cur.exhaustiveOrNull.typo == null && acc.typo == null) null else cur.exhaustiveOrNull.typo == true && acc.typo == true
166+
)
167+
}
168+
}
169+
151170
private fun List<ResponseSearch>.aggregateFacetStats(): Map<Attribute, FacetStats> {
152171
return fold(mapOf()) { acc, result ->
153172
result.facetStatsOrNull?.let { acc + it } ?: acc
@@ -164,12 +183,14 @@ internal class EndpointSearchImpl(
164183
val facets = resultsDisjunctiveFacets.aggregateFacets()
165184
val facetStats = results.aggregateFacetStats()
166185
val hierarchicalFacets = resultHierarchicalFacets.aggregateFacets()
186+
val exhaustive = results.aggregateExhaustive()
167187

168188
return results.first().copy(
169189
facetStatsOrNull = if (facetStats.isEmpty()) null else facetStats,
170190
disjunctiveFacetsOrNull = facets,
171191
hierarchicalFacetsOrNull = if (hierarchicalFacets.isEmpty()) null else hierarchicalFacets,
172-
exhaustiveFacetsCountOrNull = resultsDisjunctiveFacets.all { it.exhaustiveFacetsCountOrNull == true }
192+
exhaustiveFacetsCountOrNull = resultsDisjunctiveFacets.all { it.exhaustiveFacetsCountOrNull == true },
193+
exhaustiveOrNull = exhaustive
173194
)
174195
}
175196

client/src/commonMain/kotlin/com/algolia/search/model/response/ResponseSearch.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,30 @@ public data class ResponseSearch(
7070
* more than 50ms to be processed (this can happen when using complex filters on millions on records).
7171
* See the related [discussion][https://www.algolia.com/doc/faq/index-configuration/my-facet-and-hit-counts-are-not-accurate/]
7272
*/
73+
@Deprecated("See the `nbHits` field of the `exhaustive` object in the response.",
74+
ReplaceWith("exhaustive.nbHits")
75+
)
7376
@SerialName(Key.ExhaustiveNbHits) val exhaustiveNbHitsOrNull: Boolean? = null,
7477
/**
7578
* Whether the facet count is exhaustive (true) or approximate (false).
7679
* See the related [discussion][https://www.algolia.com/doc/faq/index-configuration/my-facet-and-hit-counts-are-not-accurate/].
7780
*/
81+
@Deprecated("See the `facetsCount` field of the `exhaustive` object in the response.",
82+
ReplaceWith("exhaustive.facetsCount")
83+
)
7884
@SerialName(Key.ExhaustiveFacetsCount) val exhaustiveFacetsCountOrNull: Boolean? = null,
85+
/**
86+
* Whether certain properties of the search response are calculated exhaustive (exact) or approximated.
87+
*
88+
* List of fields:
89+
*
90+
* `facetsCount`: Whether the facet count is exhaustive (true) or approximate (false). See the [related discussion](https://support.algolia.com/hc/en-us/articles/4406975248145-Why-are-my-facet-and-hit-counts-not-accurate-).
91+
* `facetValues`: The value is false if not all facet values are retrieved.
92+
* `nbHits`: Whether the `nbHits` is exhaustive (true) or approximate (false). When the query takes more than 50ms to be processed, the engine makes an approximation. This can happen when using complex filters on millions of records, when typo-tolerance was not exhaustive, or when enough hits have been retrieved (for example, after the engine finds 10,000 exact matches). `nbHits` is reported as non-exhaustive whenever an approximation is made, even if the approximation didn't, in the end, impact the exhaustiveness of the query.
93+
* `rulesMatch`: Rules matching exhaustiveness. The value is false if rules were enabled for this query, and could not be fully processed due a timeout. This is generally caused by the number of alternatives (such as typos) which is too large.
94+
* `typo`: Whether the `typo` search was exhaustive (true) or approximate (false). An approximation is done when the typo search query part takes more than 10% of the query budget (i.e., 5ms by default) to be processed (this can happen when a lot of typo alternatives exist for the query). This field will not be included when typo-tolerance is entirely disabled.
95+
*/
96+
@SerialName(Key.Exhaustive) val exhaustiveOrNull: Exhaustive? = null,
7997
/**
8098
* An echo of the query text. See the [Query.query] search parameter.
8199
*/
@@ -285,6 +303,9 @@ public data class ResponseSearch(
285303
*
286304
* @throws IllegalStateException if [exhaustiveNbHitsOrNull] is null
287305
*/
306+
@Deprecated("See the `nbHits` field of the `exhaustive` object in the response.",
307+
ReplaceWith("exhaustive.nbHits")
308+
)
288309
public val exhaustiveNbHits: Boolean
289310
get() = checkNotNull(exhaustiveNbHitsOrNull)
290311

@@ -294,9 +315,26 @@ public data class ResponseSearch(
294315
*
295316
* @throws IllegalStateException if [exhaustiveFacetsCountOrNull] is null
296317
*/
318+
@Deprecated("See the `facetsCount` field of the `exhaustive` object in the response.",
319+
ReplaceWith("exhaustive.facetsCount")
320+
)
297321
public val exhaustiveFacetsCount: Boolean
298322
get() = checkNotNull(exhaustiveFacetsCountOrNull)
299323

324+
/**
325+
* Whether certain properties of the search response are calculated exhaustive (exact) or approximated.
326+
*
327+
* List of fields:
328+
*
329+
* `facetsCount`: Whether the facet count is exhaustive (true) or approximate (false). See the [related discussion](https://support.algolia.com/hc/en-us/articles/4406975248145-Why-are-my-facet-and-hit-counts-not-accurate-).
330+
* `facetValues`: The value is false if not all facet values are retrieved.
331+
* `nbHits`: Whether the `nbHits` is exhaustive (true) or approximate (false). When the query takes more than 50ms to be processed, the engine makes an approximation. This can happen when using complex filters on millions of records, when typo-tolerance was not exhaustive, or when enough hits have been retrieved (for example, after the engine finds 10,000 exact matches). `nbHits` is reported as non-exhaustive whenever an approximation is made, even if the approximation didn't, in the end, impact the exhaustiveness of the query.
332+
* `rulesMatch`: Rules matching exhaustiveness. The value is false if rules were enabled for this query, and could not be fully processed due a timeout. This is generally caused by the number of alternatives (such as typos) which is too large.
333+
* `typo`: Whether the `typo` search was exhaustive (true) or approximate (false). An approximation is done when the typo search query part takes more than 10% of the query budget (i.e., 5ms by default) to be processed (this can happen when a lot of typo alternatives exist for the query). This field will not be included when typo-tolerance is entirely disabled.
334+
*/
335+
public val exhaustive: Exhaustive
336+
get() = checkNotNull(exhaustiveOrNull)
337+
300338
/**
301339
* An echo of the query text. See the [Query.query] search parameter.
302340
*

client/src/commonMain/kotlin/com/algolia/search/model/response/ResponseSearchForFacets.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.algolia.search.model.response
22

3+
import com.algolia.search.model.search.Exhaustive
34
import com.algolia.search.model.search.Facet
45
import com.algolia.search.serialize.KSerializerFacetList
56
import com.algolia.search.serialize.internal.Key
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.algolia.search.model.search
2+
3+
import com.algolia.search.serialize.internal.Key
4+
import kotlinx.serialization.SerialName
5+
import kotlinx.serialization.Serializable
6+
7+
/**
8+
* Whether certain properties of the search response are calculated exhaustive (exact) or approximated.
9+
*
10+
* List of fields:
11+
*
12+
* `facetsCount`: Whether the facet count is exhaustive (true) or approximate (false). See the [related discussion](https://support.algolia.com/hc/en-us/articles/4406975248145-Why-are-my-facet-and-hit-counts-not-accurate-).
13+
* `facetValues`: The value is false if not all facet values are retrieved.
14+
* `nbHits`: Whether the `nbHits` is exhaustive (true) or approximate (false). When the query takes more than 50ms to be processed, the engine makes an approximation. This can happen when using complex filters on millions of records, when typo-tolerance was not exhaustive, or when enough hits have been retrieved (for example, after the engine finds 10,000 exact matches). `nbHits` is reported as non-exhaustive whenever an approximation is made, even if the approximation didn't, in the end, impact the exhaustiveness of the query.
15+
* `rulesMatch`: Rules matching exhaustiveness. The value is false if rules were enabled for this query, and could not be fully processed due a timeout. This is generally caused by the number of alternatives (such as typos) which is too large.
16+
* `typo`: Whether the `typo` search was exhaustive (true) or approximate (false). An approximation is done when the typo search query part takes more than 10% of the query budget (i.e., 5ms by default) to be processed (this can happen when a lot of typo alternatives exist for the query). This field will not be included when typo-tolerance is entirely disabled.
17+
*/
18+
@Serializable
19+
public data class Exhaustive(
20+
@SerialName(Key.FacetsCount) val facetsCount: Boolean? = null,
21+
@SerialName(Key.FacetValues) val facetValues: Boolean? = null,
22+
@SerialName(Key.NbHits) val nbHits: Boolean,
23+
@SerialName(Key.RulesMatch) val rulesMatch: Boolean? = null,
24+
@SerialName(Key.Typo) val typo: Boolean? = null
25+
) {
26+
27+
}

client/src/commonMain/kotlin/com/algolia/search/model/search/ResponseFields.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public sealed class ResponseFields(override val raw: String) : Raw<String> {
2222
public object AroundLatLng : ResponseFields(Key.AroundLatLng)
2323
public object AutomaticRadius : ResponseFields(Key.AutomaticRadius)
2424
public object ExhaustiveFacetsCount : ResponseFields(Key.ExhaustiveFacetsCount)
25+
public object Exhaustive : ResponseFields(Key.Exhaustive)
2526
public object Facets : ResponseFields(Key.Facets)
2627
public object FacetsStats : ResponseFields(Key.Facets_Stats)
2728
public object Hits : ResponseFields(Key.Hits)
@@ -60,6 +61,7 @@ public sealed class ResponseFields(override val raw: String) : Raw<String> {
6061
Key.AroundLatLng -> AroundLatLng
6162
Key.AutomaticRadius -> AutomaticRadius
6263
Key.ExhaustiveFacetsCount -> ExhaustiveFacetsCount
64+
Key.Exhaustive -> Exhaustive
6365
Key.Facets -> Facets
6466
Key.Facets_Stats -> FacetsStats
6567
Key.Hits -> Hits

client/src/commonMain/kotlin/com/algolia/search/serialize/internal/Key.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ internal object Key {
102102
const val Star = "*"
103103
const val AutomaticRadius = "automaticRadius"
104104
const val ExhaustiveFacetsCount = "exhaustiveFacetsCount"
105+
const val Exhaustive = "exhaustive"
106+
const val FacetsCount = "facetsCount"
107+
const val FacetValues = "facetValues"
108+
const val RulesMatch = "rulesMatch"
105109
const val Facets_Stats = "facets_stats"
106110
const val Hits = "hits"
107111
const val Index = "index"

client/src/commonTest/kotlin/dsl/advanced/TestDSLResponseFields.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ internal class TestDSLResponseFields {
2727
AroundLatLng shouldEqual ResponseFields.AroundLatLng
2828
AutomaticRadius shouldEqual ResponseFields.AutomaticRadius
2929
ExhaustiveFacetsCount shouldEqual ResponseFields.ExhaustiveFacetsCount
30+
Exhaustive shouldEqual ResponseFields.Exhaustive
3031
Facets shouldEqual ResponseFields.Facets
3132
FacetsStats shouldEqual ResponseFields.FacetsStats
3233
Hits shouldEqual ResponseFields.Hits

client/src/commonTest/kotlin/model/search/TestResponseFields.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.algolia.search.model.search.ResponseFields.All
44
import com.algolia.search.model.search.ResponseFields.AroundLatLng
55
import com.algolia.search.model.search.ResponseFields.AutomaticRadius
66
import com.algolia.search.model.search.ResponseFields.ExhaustiveFacetsCount
7+
import com.algolia.search.model.search.ResponseFields.Exhaustive
78
import com.algolia.search.model.search.ResponseFields.Facets
89
import com.algolia.search.model.search.ResponseFields.FacetsStats
910
import com.algolia.search.model.search.ResponseFields.Hits
@@ -33,6 +34,7 @@ internal class TestResponseFields {
3334
AroundLatLng.raw shouldEqual Key.AroundLatLng
3435
AutomaticRadius.raw shouldEqual Key.AutomaticRadius
3536
ExhaustiveFacetsCount.raw shouldEqual Key.ExhaustiveFacetsCount
37+
Exhaustive.raw shouldEqual Key.Exhaustive
3638
Facets.raw shouldEqual Key.Facets
3739
FacetsStats.raw shouldEqual Key.Facets_Stats
3840
Hits.raw shouldEqual Key.Hits

client/src/commonTest/kotlin/serialize/TestKeys.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ internal class TestKeys {
108108
Key.Star shouldEqual "*"
109109
Key.AutomaticRadius shouldEqual "automaticRadius"
110110
Key.ExhaustiveFacetsCount shouldEqual "exhaustiveFacetsCount"
111+
Key.Exhaustive shouldEqual "exhaustive"
111112
Key.Facets_Stats shouldEqual "facets_stats"
112113
Key.Hits shouldEqual "hits"
113114
Key.Index shouldEqual "index"

0 commit comments

Comments
 (0)