Skip to content

Commit d0aaff3

Browse files
authored
Add preFilter to recs (#137)
1 parent 027b83a commit d0aaff3

File tree

5 files changed

+75
-13
lines changed

5 files changed

+75
-13
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,11 @@ var variationsMap: VariationsMap = VariationsMap(
330330
dtype = "array",
331331
"""{"and":[{"field":"data.brand","value":"Best Brand"}]}""",
332332
)
333+
var preFilterExpression = """{ "and": [ { "name": "Color", "value": "green" } ] }"""
334+
333335

334336
// Using RxJava
335-
ConstructorIo.getRecommendationResults(podId, selectedFacets?.map { it.key to it.value }, numResults, variationsMap = variationsMap)
337+
ConstructorIo.getRecommendationResults(podId, selectedFacets?.map { it.key to it.value }, numResults, variationsMap = variationsMap, preFilterExpression = preFilterExpression)
336338
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
337339
.subscribe {
338340
it.onValue {

library/src/main/java/io/constructor/core/ConstructorIo.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,9 +1887,10 @@ object ConstructorIo {
18871887
* @param itemId: The item id to retrieve recommendations (strategy specific)
18881888
* @param term: The term to use to refine results (strategy specific)
18891889
* @param variationsMap specify which attributes within variations should be returned
1890+
* @param preFilterExpression faceting expression to scope results
18901891
*/
1891-
fun getRecommendationResults(podId: String, facets: List<Pair<String, List<String>>>? = null, numResults: Int? = null, sectionName: String? = null, itemId: String? = null, term: String? = null, variationsMap: VariationsMap? = null): Observable<ConstructorData<RecommendationsResponse>> {
1892-
val encodedParams: ArrayList<Pair<String, String>> = getEncodedParams(numResults = numResults, sectionName = sectionName, itemId = itemId, term = term, facets = facets, variationsMap = variationsMap)
1892+
fun getRecommendationResults(podId: String, facets: List<Pair<String, List<String>>>? = null, numResults: Int? = null, sectionName: String? = null, itemId: String? = null, term: String? = null, variationsMap: VariationsMap? = null, preFilterExpression: String? = null): Observable<ConstructorData<RecommendationsResponse>> {
1893+
val encodedParams: ArrayList<Pair<String, String>> = getEncodedParams(numResults = numResults, sectionName = sectionName, itemId = itemId, term = term, facets = facets, variationsMap = variationsMap, preFilterExpression = preFilterExpression)
18931894

18941895
return dataManager.getRecommendationResults(podId, encodedParams = encodedParams.toTypedArray())
18951896
}
@@ -1917,9 +1918,10 @@ object ConstructorIo {
19171918
* @param itemId: The item id to retrieve recommendations (strategy specific)
19181919
* @param term: The term to use to refine results (strategy specific)
19191920
* @param variationsMap specify which attributes within variations should be returned
1921+
* @param preFilterExpression faceting expression to scope results
19201922
*/
1921-
suspend fun getRecommendationResultsCRT(podId: String, facets: List<Pair<String, List<String>>>? = null, numResults: Int? = null, sectionName: String? = null, itemId: String? = null, term: String? = null, variationsMap: VariationsMap? = null): RecommendationsResponse {
1922-
val encodedParams: ArrayList<Pair<String, String>> = getEncodedParams(numResults = numResults, sectionName = sectionName, itemId = itemId, term = term, facets = facets, variationsMap = variationsMap)
1923+
suspend fun getRecommendationResultsCRT(podId: String, facets: List<Pair<String, List<String>>>? = null, numResults: Int? = null, sectionName: String? = null, itemId: String? = null, term: String? = null, variationsMap: VariationsMap? = null, preFilterExpression: String? = null): RecommendationsResponse {
1924+
val encodedParams: ArrayList<Pair<String, String>> = getEncodedParams(numResults = numResults, sectionName = sectionName, itemId = itemId, term = term, facets = facets, variationsMap = variationsMap, preFilterExpression = preFilterExpression)
19231925

19241926
return dataManager.getRecommendationResultsCRT(podId, encodedParams = encodedParams.toTypedArray())
19251927
}
@@ -1950,9 +1952,11 @@ object ConstructorIo {
19501952
* @param term the term to use to refine results (strategy specific)
19511953
* @param numResults the number of results to return
19521954
* @param section the section the results will come from, i.e. "Products"
1955+
* @param variationsMap specify which attributes within variations should be returned
1956+
* @param preFilterExpression faceting expression to scope results
19531957
*/
19541958
fun getRecommendationResults(request: RecommendationsRequest): Observable<ConstructorData<RecommendationsResponse>> {
1955-
val encodedParams: ArrayList<Pair<String, String>> = getEncodedParams(facets = request.filters?.toList(), itemIds = request.itemIds, term = request.term, numResults = request.numResults, sectionName = request.section, variationsMap = request.variationsMap )
1959+
val encodedParams: ArrayList<Pair<String, String>> = getEncodedParams(facets = request.filters?.toList(), itemIds = request.itemIds, term = request.term, numResults = request.numResults, sectionName = request.section, variationsMap = request.variationsMap, preFilterExpression = request.preFilterExpression)
19561960

19571961
return dataManager.getRecommendationResults(request.podId, encodedParams = encodedParams.toTypedArray())
19581962
}

library/src/main/java/io/constructor/data/builder/RecommendationsRequest.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class RecommendationsRequest (
1313
val numResults: Int? = null,
1414
val section: String? = null,
1515
val variationsMap: VariationsMap? = null,
16+
val preFilterExpression: String? = null,
1617
) {
1718
private constructor(builder: Builder) : this(
1819
builder.podId,
@@ -22,6 +23,7 @@ class RecommendationsRequest (
2223
builder.numResults,
2324
builder.section,
2425
builder.variationsMap,
26+
builder.preFilterExpression,
2527
)
2628

2729
companion object {
@@ -37,13 +39,15 @@ class RecommendationsRequest (
3739
var term: String? = null
3840
var section: String? = null
3941
var variationsMap: VariationsMap? = null
42+
var preFilterExpression: String? = null
4043

4144
fun setFilters(facets: Map<String, List<String>>): Builder = apply { this.filters = facets }
4245
fun setItemIds(itemIds: List<String>): Builder = apply { this.itemIds = itemIds }
4346
fun setTerm(term: String): Builder = apply { this.term = term }
4447
fun setNumResults(numResults: Int): Builder = apply { this.numResults = numResults }
4548
fun setSection(section: String): Builder = apply { this.section = section }
4649
fun setVariationsMap(variationsMap: VariationsMap): Builder = apply { this.variationsMap = variationsMap }
50+
fun setPreFilterExpression(preFilterExpression: String): Builder = apply { this.preFilterExpression = preFilterExpression }
4751
fun build(): RecommendationsRequest = RecommendationsRequest(this)
4852
}
4953
}

library/src/test/java/io/constructor/core/ConstructorIoIntegrationTest.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,19 @@ class ConstructorIoIntegrationTest {
11231123
Thread.sleep(timeBetweenTests)
11241124
}
11251125

1126+
@Test
1127+
fun getRecommendationResultsCRTWithPreFilterExpressionAgainstRealResponse() {
1128+
runBlocking {
1129+
val preFilterExpression = """{"and":[{"name":"Color","value":"green"}]}"""
1130+
val recommendationResults = constructorIo.getRecommendationResultsCRT("home_page_1", preFilterExpression = preFilterExpression)
1131+
assertTrue(recommendationResults.resultId !== null)
1132+
assertTrue(recommendationResults.response!!.results!!.isNotEmpty())
1133+
assertTrue(recommendationResults.response!!.resultCount!! > 0)
1134+
assertNotNull(recommendationResults.request!!["pre_filter_expression"])
1135+
}
1136+
Thread.sleep(timeBetweenTests)
1137+
}
1138+
11261139
@Test
11271140
fun trackRecommendationResultClickAgainstRealResponse() {
11281141
val observer = constructorIo.trackRecommendationResultClickInternal(

library/src/test/java/io/constructor/core/ConstructorIoRecommendationsTest.kt

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,52 @@ class ConstructorIoRecommendationsTest {
195195
assertThat(request.requestUrl!!.encodedPath).isEqualTo("/recommendations/v1/pods/titanic")
196196
with(request.requestUrl!!) {
197197
val queryParams = mapOf(
198-
"variations_map" to """{"dtype":"array","values":{"Price":{"aggregation":"min","field":"data.facets.price"},"Country":{"aggregation":"all","field":"data.facets.country"}},"group_by":[{"name":"Country","field":"data.facets.Country"}]}""",
199-
"key" to "golden-key",
200-
"i" to "guido-the-guid",
201-
"ui" to "player-one",
202-
"s" to "79",
203-
"c" to "cioand-2.30.0",
204-
"_dt" to "1"
198+
"variations_map" to """{"dtype":"array","values":{"Price":{"aggregation":"min","field":"data.facets.price"},"Country":{"aggregation":"all","field":"data.facets.country"}},"group_by":[{"name":"Country","field":"data.facets.Country"}]}""",
199+
"key" to "golden-key",
200+
"i" to "guido-the-guid",
201+
"ui" to "player-one",
202+
"s" to "79",
203+
"c" to "cioand-2.30.0",
204+
"_dt" to "1"
205+
)
206+
assertThat(queryParameterNames).containsExactlyInAnyOrderElementsOf(queryParams.keys)
207+
208+
queryParams.forEach { (key, value) ->
209+
if (key == "_dt") {
210+
assertThat(queryParameter(key)).containsOnlyDigits()
211+
} else {
212+
assertThat(queryParameter(key)).isEqualTo(value)
213+
}
214+
}
215+
}
216+
}
217+
218+
@Test
219+
fun getRecommendationResultsWithPreFilterExpressionUsingBuilder() {
220+
val mockResponse = MockResponse().setResponseCode(200).setBody(TestDataLoader.loadAsString("recommendation_response.json"))
221+
mockServer.enqueue(mockResponse)
222+
val preFilterExpression = """{"and":[{"name":"Country","value":"US"}]}"""
223+
val recommendationsRequest = RecommendationsRequest.Builder("titanic")
224+
.setPreFilterExpression(preFilterExpression)
225+
.build()
226+
val observer = constructorIo.getRecommendationResults(recommendationsRequest).test()
227+
observer.assertComplete().assertValue {
228+
var recommendationResponse = it.get()
229+
recommendationResponse?.response?.results?.isNotEmpty()!!
230+
}
231+
observer.assertNoErrors()
232+
233+
val request = mockServer.takeRequest()
234+
assertThat(request.requestUrl!!.encodedPath).isEqualTo("/recommendations/v1/pods/titanic")
235+
with(request.requestUrl!!) {
236+
val queryParams = mapOf(
237+
"pre_filter_expression" to preFilterExpression,
238+
"key" to "golden-key",
239+
"i" to "guido-the-guid",
240+
"ui" to "player-one",
241+
"s" to "79",
242+
"c" to "cioand-2.30.0",
243+
"_dt" to "1"
205244
)
206245
assertThat(queryParameterNames).containsExactlyInAnyOrderElementsOf(queryParams.keys)
207246

0 commit comments

Comments
 (0)