Skip to content

Commit

Permalink
Merge pull request #153 from AnyRoad/add_matched_queries
Browse files Browse the repository at this point in the history
adds matched_queries field for the Hit object
  • Loading branch information
jillesvangurp authored Nov 26, 2024
2 parents 652ca60 + 0ec404d commit 1cc78aa
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import kotlinx.serialization.*
import kotlinx.serialization.json.*

typealias Aggregations = JsonObject
typealias MatchedQueries = JsonElement

@Suppress("unused")
@Serializable
Expand Down Expand Up @@ -54,6 +55,17 @@ data class SearchResponse(
override val version: Long?,
@SerialName("_explanation")
val explanation: JsonObject?,
/**
* If named queries are used, the response includes a matched_queries property for each hit.
* There are two forms of the matched_queries response:
* - if include_named_queries_score was set, response includes map with named query and score
* - otherwise just list of the named queries.
* so the field is just a JsonElement with 2 extension functions:
* - MatchedQueries::names()
* - MatchedQueries::scoreByName()
*/
@SerialName("matched_queries")
val matchedQueries: MatchedQueries?,
) : SourceInformation

@Serializable
Expand Down Expand Up @@ -425,3 +437,17 @@ fun Aggregations?.sumAggregationResult(name: String, json: Json = DEFAULT_JSON):
fun Aggregations?.sumAggregationResult(name: Enum<*>, json: Json = DEFAULT_JSON): TopHitsAggregationResult =
getAggResult(name.name, json)

/**
* If include_named_queries_score parameter is not `true` only ES returns only query names for each Hit.
* If include_named_queries_score is `true` please use the `scoreByName` function.
*/
fun MatchedQueries?.names(json: Json = DEFAULT_JSON): List<String> =
this?.let { json.decodeFromJsonElement(it) } ?: emptyList()

/**
* The request parameter named include_named_queries_score controls whether scores associated
* with the matched queries are returned or not. When set, the response includes a matched_queries map
* that contains the name of the query that matched as a key and its associated score as the value.
*/
fun MatchedQueries?.scoreByName(json: Json = DEFAULT_JSON): Map<String, Double> =
this?.let { json.decodeFromJsonElement(it) } ?: emptyMap()
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,60 @@ class SearchTest : SearchTestBase() {
hits[1].highlight shouldBe null
}
}

@Test
fun shouldReturnMatchedNamedQueries() = coRun {
testDocumentIndex { index ->

client.indexDocument(index, TestDocument("foo bar").json(false), refresh = Refresh.WaitFor, id = "1")
client.indexDocument(index, TestDocument("fooo").json(false), refresh = Refresh.WaitFor, id = "2")
client.indexDocument(index, TestDocument("bar").json(false), refresh = Refresh.WaitFor, id = "3")

val result = client.search("$index,$index") {
query = match(TestDocument::name, "bar") {
put("_name", "name_filter")
}
}
result.hits!!.hits shouldHaveSize 2
result.hits!!.hits.map { it.matchedQueries.names() } shouldBe listOf(listOf("name_filter"), listOf("name_filter"))
}
}

@Test
fun shouldReturnMatchedNamedQueriesWithScores() = coRun {
testDocumentIndex { index ->

client.indexDocument(index, TestDocument("foo bar").json(false), refresh = Refresh.WaitFor, id = "1")
client.indexDocument(index, TestDocument("fooo").json(false), refresh = Refresh.WaitFor, id = "2")
client.indexDocument(index, TestDocument("bar").json(false), refresh = Refresh.WaitFor, id = "3")

val result =
client.search("$index,$index", extraParameters = mapOf("include_named_queries_score" to "true")) {
query = match(TestDocument::name, "bar") {
put("_name", "name_filter")
}
}
result.hits!!.hits shouldHaveSize 2
val scoreByQueryName = result.hits!!.hits.first().matchedQueries.scoreByName()
scoreByQueryName.size shouldBe 1
scoreByQueryName.containsKey("name_filter") shouldBe true
}
}

@Test
fun shouldReturnEmptyMatchedNamedQueriesIfRequestHasNoNamedQueries() = coRun {
testDocumentIndex { index ->

client.indexDocument(index, TestDocument("foo bar").json(false), refresh = Refresh.WaitFor, id = "1")
client.indexDocument(index, TestDocument("fooo").json(false), refresh = Refresh.WaitFor, id = "2")
client.indexDocument(index, TestDocument("bar").json(false), refresh = Refresh.WaitFor, id = "3")

val result = client.search("$index,$index") {
query = match(TestDocument::name, "bar")
}
result.hits!!.hits shouldHaveSize 2
result.hits!!.hits.map { it.matchedQueries.names() } shouldBe listOf(listOf(), listOf())
result.hits!!.hits.map { it.matchedQueries.scoreByName() } shouldBe listOf(mapOf(), mapOf())
}
}
}

0 comments on commit 1cc78aa

Please sign in to comment.