diff --git a/Package.resolved b/Package.resolved index 595e7db..dcf3367 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-custom-dump.git", "state" : { - "revision" : "f01efb26f3a192a0e88dcdb7c3c391ec2fc25d9c", - "version" : "1.3.0" + "revision" : "82645ec760917961cfa08c9c0c7104a57a0fa4b1", + "version" : "1.3.3" } }, { @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", "state" : { - "revision" : "6f30bdba373bbd7fbfe241dddd732651f2fbd1e2", - "version" : "1.1.2" + "revision" : "27d767d643fa2cf083d0a73d74fa84cacb53e85c", + "version" : "1.4.1" } } ], diff --git a/Sources/ElasticsearchQueryBuilder/Components.swift b/Sources/ElasticsearchQueryBuilder/Components.swift index 5968258..1ff87b4 100644 --- a/Sources/ElasticsearchQueryBuilder/Components.swift +++ b/Sources/ElasticsearchQueryBuilder/Components.swift @@ -199,6 +199,22 @@ extension esb { } } + /// Adds `sort` block to the query syntax. + public struct Sort: DictComponent { + var component: Component + public init(@QueryArrayBuilder component: () -> Component) { + self.component = component() + } + public func makeDict() -> QueryDict { + let values: [QueryDict] = self.component.makeCompactArray() + if values.isEmpty { + return [:] + } else { + return [ "sort" : .array(values.map(QueryValue.dict)) ] + } + } + } + /// Adds `term` block to the query syntax. /// /// Excludes the component if value is nil. diff --git a/Tests/ElasticsearchQueryBuilderTests/ComponentTests.swift b/Tests/ElasticsearchQueryBuilderTests/ComponentTests.swift index 8dcd9a0..c67b212 100644 --- a/Tests/ElasticsearchQueryBuilderTests/ComponentTests.swift +++ b/Tests/ElasticsearchQueryBuilderTests/ComponentTests.swift @@ -8,7 +8,7 @@ final class NothingTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.Nothing() } - XCTAssertNoDifference(build().makeQuery(), [:]) + expectNoDifference(build().makeQuery(), [:]) } } @@ -17,7 +17,7 @@ final class KeyTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.Key("boost", .float(1.2)) } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "boost": 1.2 ]) } @@ -29,7 +29,7 @@ final class KeyTests: XCTestCase { ] } } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "match_bool_prefix": [ "message": "quick brown f" ] @@ -39,7 +39,7 @@ final class KeyTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.Key("match", .dict([:])) } - XCTAssertNoDifference(build().makeQuery(), [:]) + expectNoDifference(build().makeQuery(), [:]) } } @@ -57,7 +57,7 @@ final class ComposableBuilderTests: XCTestCase { makeKey() } } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "query": [ "match_bool_prefix": [ "message": "quick brown f" @@ -80,7 +80,7 @@ final class ComposableBuilderTests: XCTestCase { makeKey(true) } } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "filter": [ [ "match_bool_prefix": [ @@ -107,7 +107,7 @@ final class ComposableBuilderTests: XCTestCase { makeKey(true, 3) } } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "filter": [ [ "match_bool_prefix": [ @@ -135,7 +135,7 @@ final class QueryTests: XCTestCase { } } } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "query": [ "match_bool_prefix": [ "message": "quick brown f" @@ -149,7 +149,7 @@ final class QueryTests: XCTestCase { esb.Key("match", .dict([:])) } } - XCTAssertNoDifference(build().makeQuery(), [:]) + expectNoDifference(build().makeQuery(), [:]) } } @@ -196,7 +196,7 @@ final class BoolTests: XCTestCase { } } } - XCTAssertNoDifference(build(true).makeQuery(), [ + expectNoDifference(build(true).makeQuery(), [ "bool": [ "minimum_should_match": 1, "should": [ @@ -229,7 +229,7 @@ final class BoolTests: XCTestCase { ] ] ]) - XCTAssertNoDifference(build(false).makeQuery(), [ + expectNoDifference(build(false).makeQuery(), [ "bool": [ "minimum_should_match": 1 ] @@ -252,7 +252,44 @@ final class BoolTests: XCTestCase { } } } - XCTAssertNoDifference(build().makeQuery(), [:]) + expectNoDifference(build().makeQuery(), [:]) + } +} + +final class SortTests: XCTestCase { + func testBuild() throws { + @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { + esb.Sort { + esb.Key("_score") { + [ "order": "desc" ] + } + esb.Key("name") { + [ "order": "asc" ] + } + } + } + expectNoDifference(build().makeQuery(), [ + "sort": [ + [ + "_score": [ "order": "desc" ] + ], + [ + "name": [ "order": "asc" ] + ] + ] + ]) + } + func testBuildEmpty() throws { + @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { + esb.Sort { + if false { + esb.Key("_score") { + [ "order": "desc" ] + } + } + } + } + expectNoDifference(build().makeQuery(), [:]) } } @@ -261,7 +298,7 @@ final class TermTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.Term("name", "joe") } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "term": [ "name": "joe" ] ]) } @@ -269,7 +306,7 @@ final class TermTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.Term("name", nil) } - XCTAssertNoDifference(build().makeQuery(), [:]) + expectNoDifference(build().makeQuery(), [:]) } } @@ -278,7 +315,7 @@ final class TermsORTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.TermsOR("name", ["joe", "mary"]) } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "terms": [ "name": ["joe", "mary"] ] ]) } @@ -286,7 +323,7 @@ final class TermsORTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.TermsOR("name", []) } - XCTAssertNoDifference(build().makeQuery(), [:]) + expectNoDifference(build().makeQuery(), [:]) } } @@ -297,7 +334,7 @@ final class TermsANDTests: XCTestCase { esb.TermsAND("name", ["joe", "mary"]) } } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "filter": [ [ "term": [ "name": "joe" ] ], [ "term": [ "name": "mary" ] ], @@ -310,7 +347,7 @@ final class TermsANDTests: XCTestCase { esb.TermsAND("name", []) } } - XCTAssertNoDifference(build().makeQuery(), [:]) + expectNoDifference(build().makeQuery(), [:]) } } @@ -319,7 +356,7 @@ final class KNearestNeighborTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.kNearestNeighbor("vector_field", [1,2,3]) } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "knn": [ "field": "vector_field", "query_vector": [1.0, 2.0, 3.0], @@ -341,7 +378,7 @@ final class KNearestNeighborTests: XCTestCase { } } } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "knn": [ "field": "vector_field", "query_vector": [1.0, 2.0, 3.0], @@ -385,7 +422,7 @@ final class FunctionScoreTests: XCTestCase { } } } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "function_score": [ "bool": [ "should": [ @@ -415,13 +452,13 @@ final class SearchPaginationTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.Pagination() } - XCTAssertNoDifference(build().makeQuery(), [:]) + expectNoDifference(build().makeQuery(), [:]) } func testBuildFirst() throws { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.Pagination(from: 10) } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "from": 10 ]) } @@ -429,7 +466,7 @@ final class SearchPaginationTests: XCTestCase { @ElasticsearchQueryBuilder func build() -> some esb.QueryDSL { esb.Pagination(from: 10, size: 20) } - XCTAssertNoDifference(build().makeQuery(), [ + expectNoDifference(build().makeQuery(), [ "from": 10, "size": 20, ])