From 03973eedbb5e4d755609b56b7bebf937783d5a67 Mon Sep 17 00:00:00 2001 From: Christopher Sundersingh <83315412+sundersc@users.noreply.github.com> Date: Thu, 1 Jul 2021 08:13:44 -0700 Subject: [PATCH] feat: category graphql/searchable sort multiple fields (#7553) --- ...aphql-searchable-transformer.tests.ts.snap | 53 ++++++++++++------- .../src/generate-resolver-vtl.ts | 44 +++++++++++---- .../src/graphql-searchable-transformer.ts | 2 +- 3 files changed, 69 insertions(+), 30 deletions(-) diff --git a/packages/amplify-graphql-searchable-transformer/src/__tests__/__snapshots__/amplify-graphql-searchable-transformer.tests.ts.snap b/packages/amplify-graphql-searchable-transformer/src/__tests__/__snapshots__/amplify-graphql-searchable-transformer.tests.ts.snap index a778d0106a2..c272cbeb6a0 100644 --- a/packages/amplify-graphql-searchable-transformer/src/__tests__/__snapshots__/amplify-graphql-searchable-transformer.tests.ts.snap +++ b/packages/amplify-graphql-searchable-transformer/src/__tests__/__snapshots__/amplify-graphql-searchable-transformer.tests.ts.snap @@ -102,7 +102,7 @@ type SearchablePostConnection { } type Query { - searchPosts(filter: SearchablePostFilterInput, sort: SearchablePostSortInput, limit: Int, nextToken: String, from: Int): SearchablePostConnection + searchPosts(filter: SearchablePostFilterInput, sort: [SearchablePostSortInput], limit: Int, nextToken: String, from: Int): SearchablePostConnection getPost(id: ID!): Post listPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String): ModelPostConnection } @@ -607,17 +607,34 @@ $util.toJson($ListRequest) ## [End] Get ResponseTemplate. **", "Query.searchPosts.req.vtl": "#set( $indexPath = \\"/post/doc/_search\\" ) #set( $nonKeywordFields = [] ) +#set( $sortValues = [] ) +#set( $primaryKey = \\"id\\" ) #if( $util.isNullOrEmpty($context.args.sort) ) - #set( $sortDirection = \\"desc\\" ) - #set( $sortField = \\"id\\" ) -#else - #set( $sortDirection = $util.defaultIfNull($context.args.sort.direction, \\"desc\\") ) - #set( $sortField = $util.defaultIfNull($context.args.sort.field, \\"id\\") ) -#end -#if( $nonKeywordFields.contains($sortField) ) - #set( $sortField0 = $util.toJson($sortField) ) + #if( $nonKeywordFields.contains($primaryKey) ) + #set( $sortField = $util.toJson($primaryKey) ) + #else + #set( $sortField = $util.toJson(\\"\${primaryKey}.keyword\\") ) + #end + #set( $sortDirection = $util.toJson({\\"order\\": \\"desc\\"}) ) + $util.qr($sortValues.add(\\"{$sortField: $sortDirection}\\")) #else - #set( $sortField0 = $util.toJson(\\"\${sortField}.keyword\\") ) + #foreach( $sortItem in $context.args.sort ) + #if( $util.isNullOrEmpty($sortItem.field) ) + #if( $nonKeywordFields.contains($primaryKey) ) + #set( $sortField = $util.toJson($primaryKey) ) + #else + #set( $sortField = $util.toJson(\\"\${primaryKey}.keyword\\") ) + #end + #else + #if( $nonKeywordFields.contains($sortItem.field) ) + #set( $sortField = $util.toJson($sortItem.field) ) + #else + #set( $sortField = $util.toJson(\\"\${sortItem.field}.keyword\\") ) + #end + #end + #set( $sortDirection = $util.toJson({\\"order\\": $sortItem.direction}) ) + $util.qr($sortValues.add(\\"{$sortField: $sortDirection}\\")) + #end #end { \\"version\\": \\"2018-05-29\\", @@ -625,10 +642,10 @@ $util.toJson($ListRequest) \\"path\\": \\"$indexPath\\", \\"params\\": { \\"body\\": { - #if( $context.args.nextToken )\\"search_after\\": [$util.toJson($context.args.nextToken)], #end + #if( $context.args.nextToken )\\"search_after\\": $util.base64Decode($context.args.nextToken), #end #if( $context.args.from )\\"from\\": $context.args.from, #end \\"size\\": #if( $context.args.limit ) $context.args.limit #else 100 #end, - \\"sort\\": [{$sortField0: { \\"order\\" : $util.toJson($sortDirection) }}], + \\"sort\\": $sortValues, \\"version\\": false, \\"query\\": #if( $context.args.filter ) $util.transform.toElasticsearchQueryDSL($ctx.args.filter) @@ -643,7 +660,7 @@ $util.transform.toElasticsearchQueryDSL($ctx.args.filter) "Query.searchPosts.res.vtl": "#set( $es_items = [] ) #foreach( $entry in $context.result.hits.hits ) #if( !$foreach.hasNext ) - #set( $nextToken = $entry.sort.get(0) ) + #set( $nextToken = $util.base64Encode($util.toJson($entry.sort)) ) #end $util.qr($es_items.add($entry.get(\\"_source\\"))) #end @@ -791,8 +808,8 @@ type SearchablePostConnection { } type Query { - searchPosts(filter: SearchablePostFilterInput, sort: SearchablePostSortInput, limit: Int, nextToken: String, from: Int): SearchablePostConnection - searchUsers(filter: SearchableUserFilterInput, sort: SearchableUserSortInput, limit: Int, nextToken: String, from: Int): SearchableUserConnection + searchPosts(filter: SearchablePostFilterInput, sort: [SearchablePostSortInput], limit: Int, nextToken: String, from: Int): SearchablePostConnection + searchUsers(filter: SearchableUserFilterInput, sort: [SearchableUserSortInput], limit: Int, nextToken: String, from: Int): SearchableUserConnection getPost(id: ID!): Post listPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String): ModelPostConnection getUser(id: ID!): User @@ -1110,7 +1127,7 @@ type SearchablePostConnection { } type Query { - searchPosts(filter: SearchablePostFilterInput, sort: SearchablePostSortInput, limit: Int, nextToken: String, from: Int): SearchablePostConnection + searchPosts(filter: SearchablePostFilterInput, sort: [SearchablePostSortInput], limit: Int, nextToken: String, from: Int): SearchablePostConnection getPost(id: ID!): Post listPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String): ModelPostConnection } @@ -1361,7 +1378,7 @@ type SearchablePostConnection { } type Query { - customSearchPost(filter: SearchablePostFilterInput, sort: SearchablePostSortInput, limit: Int, nextToken: String, from: Int): SearchablePostConnection + customSearchPost(filter: SearchablePostFilterInput, sort: [SearchablePostSortInput], limit: Int, nextToken: String, from: Int): SearchablePostConnection getPost(id: ID!): Post listPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String): ModelPostConnection } @@ -1612,7 +1629,7 @@ type SearchablePostConnection { } type Query { - searchPosts(filter: SearchablePostFilterInput, sort: SearchablePostSortInput, limit: Int, nextToken: String, from: Int): SearchablePostConnection + searchPosts(filter: SearchablePostFilterInput, sort: [SearchablePostSortInput], limit: Int, nextToken: String, from: Int): SearchablePostConnection getPost(id: ID!): Post listPosts(filter: ModelPostFilterInput, limit: Int, nextToken: String): ModelPostConnection } diff --git a/packages/amplify-graphql-searchable-transformer/src/generate-resolver-vtl.ts b/packages/amplify-graphql-searchable-transformer/src/generate-resolver-vtl.ts index 032537c0855..6e7b1950519 100644 --- a/packages/amplify-graphql-searchable-transformer/src/generate-resolver-vtl.ts +++ b/packages/amplify-graphql-searchable-transformer/src/generate-resolver-vtl.ts @@ -25,23 +25,45 @@ export function requestTemplate(primaryKey: string, nonKeywordFields: Expression compoundExpression([ set(ref('indexPath'), str(`/${type.toLowerCase()}/doc/_search`)), set(ref('nonKeywordFields'), list(nonKeywordFields)), + set(ref('sortValues'), list([])), + set(ref('primaryKey'), str(primaryKey)), ifElse( ref('util.isNullOrEmpty($context.args.sort)'), - compoundExpression([set(ref('sortDirection'), str('desc')), set(ref('sortField'), str(primaryKey))]), compoundExpression([ - set(ref('sortDirection'), ref('util.defaultIfNull($context.args.sort.direction, "desc")')), - set(ref('sortField'), ref(`util.defaultIfNull($context.args.sort.field, "${primaryKey}")`)), + ifElse( + ref('nonKeywordFields.contains($primaryKey)'), + set(ref('sortField'), ref('util.toJson($primaryKey)')), + set(ref('sortField'), ref('util.toJson("${primaryKey}.keyword")')), + ), + set(ref('sortDirection'), ref('util.toJson({"order": "desc"})')), + qref('$sortValues.add("{$sortField: $sortDirection}")'), ]), - ), - ifElse( - ref('nonKeywordFields.contains($sortField)'), - compoundExpression([set(ref('sortField0'), ref('util.toJson($sortField)'))]), - compoundExpression([set(ref('sortField0'), ref('util.toJson("${sortField}.keyword")'))]), + forEach( + ref('sortItem'), + ref('context.args.sort'), + [ + ifElse( + ref('util.isNullOrEmpty($sortItem.field)'), + ifElse( + ref('nonKeywordFields.contains($primaryKey)'), + set(ref('sortField'), ref('util.toJson($primaryKey)')), + set(ref('sortField'), ref('util.toJson("${primaryKey}.keyword")')), + ), + ifElse( + ref('nonKeywordFields.contains($sortItem.field)'), + set(ref('sortField'), ref('util.toJson($sortItem.field)')), + set(ref('sortField'), ref('util.toJson("${sortItem.field}.keyword")')), + ), + ), + set(ref('sortDirection'), ref('util.toJson({"order": $sortItem.direction})')), + qref('$sortValues.add("{$sortField: $sortDirection}")'), + ], + ), ), ElasticsearchMappingTemplate.searchItem({ path: str('$indexPath'), size: ifElse(ref('context.args.limit'), ref('context.args.limit'), int(ResourceConstants.DEFAULT_SEARCHABLE_PAGE_LIMIT), true), - search_after: list([ref('util.toJson($context.args.nextToken)')]), + search_after: ref('util.base64Decode($context.args.nextToken)'), from: ref('context.args.from'), version: bool(includeVersion), query: ifElse( @@ -51,7 +73,7 @@ export function requestTemplate(primaryKey: string, nonKeywordFields: Expression match_all: obj({}), }), ), - sort: list([raw('{$sortField0: { "order" : $util.toJson($sortDirection) }}')]), + sort: ref('sortValues'), }), ]), ); @@ -62,7 +84,7 @@ export function responseTemplate(includeVersion = false) { compoundExpression([ set(ref('es_items'), list([])), forEach(ref('entry'), ref('context.result.hits.hits'), [ - iff(raw('!$foreach.hasNext'), set(ref('nextToken'), ref('entry.sort.get(0)'))), + iff(raw('!$foreach.hasNext'), set(ref('nextToken'), ref('util.base64Encode($util.toJson($entry.sort))'))), ...getSourceMapper(includeVersion), ]), toJson( diff --git a/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts b/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts index ef36cd4827f..3ab9a97c453 100644 --- a/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts +++ b/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts @@ -173,7 +173,7 @@ export class SearchableModelTransformer extends TransformerPluginBase { fieldName, [ makeInputValueDefinition('filter', makeNamedType(`Searchable${definition.name.value}FilterInput`)), - makeInputValueDefinition('sort', makeNamedType(`Searchable${definition.name.value}SortInput`)), + makeInputValueDefinition('sort', makeListType(makeNamedType(`Searchable${definition.name.value}SortInput`))), makeInputValueDefinition('limit', makeNamedType('Int')), makeInputValueDefinition('nextToken', makeNamedType('String')), makeInputValueDefinition('from', makeNamedType('Int')),