jillesvangurp / kt-search

Multi platform kotlin client for Elasticsearch & Opensearch with easily extendable Kotlin DSLs for queries, mappings, bulk, and more.
MIT License
95 stars 23 forks source link

[FEAT] script based sorting support #130

Closed yonghee12 closed 2 months ago

yonghee12 commented 2 months ago

Describe the enhancement

Add support to the script based sorting feature

SearchDSL().apply {
    sort {
        addScript(
            order = SortOrder.ASC,
            type = "number",
            source = "doc['field_name'].value * params.factor;",
            lang = "painless",
            params = mapOf("factor" to 1.1),
        )
    }
}

Why is this needed?

Screen Shot 2024-04-11 at 6 21 50 PM

Sometimes business requirements require complex sorting logic. elastic search query can solve this with script-based sorting(e.g. https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html#script-based-sorting), and it would be nice to support this in kt-search as well. Also, you can query basic field name based sorting and script based sorting in one sort array to handle complex requirements.

How do you think it should be done?

If you add the methods below inside the SortBuilder, you should be able to use them in conjunction with your existing sorting methods.

fun addScript(
    order: SortOrder = SortOrder.DESC,
    type: String,
    source: String,
    params: Map<String, Any>? = emptyMap(),
    lang: String? = null,
) {
    _sortFields.add(
        withJsonDsl {
            this["_script"] = withJsonDsl {
                this["order"] = order.name
                this["type"] = type
                this["script"] = scriptBuilder(source, params, lang)
            }
        },
    )
}

private fun scriptBuilder(
    source: String,
    params: Map<String, Any>? = emptyMap(),
    lang: String? = "painless",
): JsonDsl {
    return withJsonDsl {
        this["source"] = source
        this["lang"] = lang
        if (params?.isNotEmpty() == true) {
            this["params"] = withJsonDsl {
                params.forEach { (key, value) -> this[key] = value }
            }
        }
    }
}

Will you be able to help with a pull request?

Yes

jillesvangurp commented 2 months ago

Please go ahead with the PR if you have time.

yonghee12 commented 2 months ago

closed by https://github.com/jillesvangurp/kt-search/pull/131