Skip to content

Commit

Permalink
Support for more sort types
Browse files Browse the repository at this point in the history
  • Loading branch information
lynxpluto authored and ihostage committed Oct 13, 2022
1 parent 45e2d43 commit 3e9ea53
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package org.taymyr.lagom.elasticsearch.search.dsl

import com.fasterxml.jackson.annotation.JsonProperty
import org.taymyr.lagom.elasticsearch.script.Script
import org.taymyr.lagom.elasticsearch.search.dsl.query.Order
import org.taymyr.lagom.elasticsearch.search.dsl.query.Query
import org.taymyr.lagom.elasticsearch.search.dsl.query.Sort
import org.taymyr.lagom.elasticsearch.search.dsl.query.aggregation.Aggregation
import org.taymyr.lagom.elasticsearch.search.dsl.query.highlight.Highlight
import org.taymyr.lagom.elasticsearch.search.dsl.query.script.ScriptField
Expand All @@ -24,7 +24,7 @@ data class SearchRequest @JvmOverloads constructor(
@JsonProperty("post_filter")
val postFilter: Query? = null,
val suggest: Map<String, Suggest>? = null,
val sort: List<Order>? = null,
val sort: List<Sort>? = null,
@JsonProperty("min_score")
val minScore: Double? = null,
@JsonProperty("search_after")
Expand All @@ -42,7 +42,7 @@ data class SearchRequest @JvmOverloads constructor(
private var aggs: MutableMap<String, Aggregation> = mutableMapOf()
private var postFilter: Query? = null
private var suggest: MutableMap<String, Suggest> = mutableMapOf()
private var sort: MutableList<Order> = mutableListOf()
private var sort: MutableList<Sort> = mutableListOf()
private var minScore: Double? = null
private var searchAfter: MutableList<Any> = mutableListOf()
private var source: SourceFilter<*>? = null
Expand All @@ -57,8 +57,8 @@ data class SearchRequest @JvmOverloads constructor(
fun postFilter(postFilter: Query) = apply { this.postFilter = postFilter }
fun suggest(suggest: Map<String, Suggest>) = apply { this.suggest.putAll(suggest) }
fun suggest(name: String, suggest: Suggest) = apply { this.suggest[name] = suggest }
fun sort(vararg sort: Order) = apply { this.sort.addAll(sort) }
fun sort(sort: List<Order>) = apply { this.sort.addAll(sort) }
fun sort(vararg sort: Sort) = apply { this.sort.addAll(sort) }
fun sort(sort: List<Sort>) = apply { this.sort.addAll(sort) }
fun minScore(minScore: Double) = apply { this.minScore = minScore }
fun searchAfter(vararg searchAfter: Any) = apply { this.searchAfter.addAll(searchAfter) }
fun searchAfter(searchAfter: List<Any>) = apply { this.searchAfter.addAll(searchAfter) }
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package org.taymyr.lagom.elasticsearch.search.dsl.query

import com.fasterxml.jackson.annotation.JsonValue
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import org.taymyr.lagom.elasticsearch.script.Script

interface Sort

@JsonSerialize(using = Order.OrderSerializer::class)
abstract class Order(private val value: String) : Sort {

abstract val expr: String

data class AscOrder(override val expr: String) : Order("asc")
data class DescOrder(override val expr: String) : Order("desc")

class OrderSerializer : JsonSerializer<Order>() {
override fun serialize(value: Order?, gen: JsonGenerator?, serializers: SerializerProvider?) {
gen?.run {
value?.let { order ->
writeStartObject()
writeObjectField(order.expr, order.value)
writeEndObject()
}
}
}
}

companion object {
@JvmStatic
fun asc(expr: String) = AscOrder(expr)

@JvmStatic
fun desc(expr: String) = DescOrder(expr)
}
}

enum class SortDirection(@JsonValue val value: String) {
ASC("asc"), DESC("desc")
}

enum class SortMode(@JsonValue val value: String) {
MIN("min"), MAX("max"), SUM("sum"), AVG("avg"), MEDIAN("median")
}

data class FieldSortSpec(val order: SortDirection, val mode: SortMode? = null) {
companion object {
@JvmOverloads
@JvmStatic
fun asc(mode: SortMode? = null) = FieldSortSpec(SortDirection.ASC, mode)

@JvmOverloads
@JvmStatic
fun desc(mode: SortMode? = null) = FieldSortSpec(SortDirection.DESC, mode)
}
}

@JsonSerialize(using = FieldSort.FieldSortSerializer::class)
data class FieldSort(val field: String, val sort: FieldSortSpec) : Sort {
class FieldSortSerializer : JsonSerializer<FieldSort>() {
override fun serialize(value: FieldSort?, gen: JsonGenerator?, serializers: SerializerProvider?) {
gen?.apply {
value?.let {
writeStartObject()
writeObjectField(it.field, it.sort)
writeEndObject()
}
}
}
}

companion object {
@JvmStatic
fun fieldSort(field: String, sort: FieldSortSpec) = FieldSort(field, sort)
}
}

@JsonSerialize(using = ScriptSort.ScriptSortSerializer::class)
data class ScriptSort(val type: String, val script: Script, val order: SortDirection) : Sort {
class ScriptSortSerializer : JsonSerializer<ScriptSort>() {
override fun serialize(value: ScriptSort?, gen: JsonGenerator?, serializers: SerializerProvider?) {
gen?.apply {
value?.let {
writeStartObject()
writeFieldName("_script")
writeStartObject()
writeObjectField("type", it.type)
writeObjectField("script", it.script)
writeObjectField("order", it.order)
writeEndObject()
writeEndObject()
}
}
}
}

companion object {
@JvmStatic
fun scriptSort(type: String, script: Script, order: SortDirection) = ScriptSort(type, script, order)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,23 @@
import org.taymyr.lagom.elasticsearch.TestDocument.TestDocumentResult;
import org.taymyr.lagom.elasticsearch.script.Script;
import org.taymyr.lagom.elasticsearch.search.dsl.SuggestResult.SuggestOption;
import org.taymyr.lagom.elasticsearch.search.dsl.query.FieldSort;
import org.taymyr.lagom.elasticsearch.search.dsl.query.FieldSortSpec;
import org.taymyr.lagom.elasticsearch.search.dsl.query.MatchAllQuery;
import org.taymyr.lagom.elasticsearch.search.dsl.query.Order;
import org.taymyr.lagom.elasticsearch.search.dsl.query.ScriptSort;
import org.taymyr.lagom.elasticsearch.search.dsl.query.SortDirection;
import org.taymyr.lagom.elasticsearch.search.dsl.query.SortMode;
import org.taymyr.lagom.elasticsearch.search.dsl.query.aggregation.TermsAggregation;
import org.taymyr.lagom.elasticsearch.search.dsl.query.compound.BoolQuery;
import org.taymyr.lagom.elasticsearch.search.dsl.query.script.ScriptQuery;
import org.taymyr.lagom.elasticsearch.search.dsl.query.suggest.CompletionSuggest;
import org.taymyr.lagom.elasticsearch.search.dsl.query.term.IdsQuery;
import org.taymyr.lagom.elasticsearch.search.dsl.query.term.TermQuery;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
Expand Down Expand Up @@ -213,4 +221,31 @@ void shouldSerializeSourceFilter() {
expected = resourceAsString("org/taymyr/lagom/elasticsearch/search/dsl/query/source/source_includes_excludes.json");
assertThatJson(actual).isEqualTo(expected);
}

@Test
@DisplayName("successfully serialize search request with different sort types")
void shouldSuccessfullySerializeSortTypes() {
Map<String, Object> params = new HashMap<>();
params.put("a", "foo");
SearchRequest request = SearchRequest.builder()
.sort(
Order.asc("field_a"),
FieldSort.fieldSort("field_b", FieldSortSpec.asc(SortMode.MAX)),
FieldSort.fieldSort("field_c", FieldSortSpec.desc()),
ScriptSort.scriptSort(
"number",
Script.builder()
.lang("painless")
.source("doc['field_c'].value == params.a ? 1 : 0")
.params(params)
.build(),
SortDirection.ASC
)
)
.query(MatchAllQuery.of())
.build();
String actual = serializeRequest(request, SearchRequest.class);
String expected = resourceAsString("org/taymyr/lagom/elasticsearch/search/dsl/request-sort.json");
assertThatJson(actual).isEqualTo(expected);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"sort": [
{ "field_a": "asc" },
{ "field_b": { "order": "asc", "mode": "max" } },
{ "field_c": { "order": "desc" } },
{
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": "doc['field_c'].value == params.a ? 1 : 0",
"params": {
"a": "foo"
}
},
"order": "asc"
}
}
],
"query": {
"match_all": {}
}
}

0 comments on commit 3e9ea53

Please sign in to comment.