Skip to content

Commit 2f490fd

Browse files
authored
Include edge in WITH statement before ORDER BY (aws#114)
Fixed nested edge subqueries with sorting to pass along the edge in WITH statement before the ORDER BY, otherwise neptune will return a 400 bad request error if the edge is referenced later in the query.
1 parent 1e5e848 commit 2f490fd

File tree

3 files changed

+46
-5
lines changed

3 files changed

+46
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,7 @@ permissions and limitations under the License.
103103
arguments ([#108](https://github.com/aws/amazon-neptune-for-graphql/pull/108))
104104
* Changed resolver to use `graphql` `parse` instead of `graphql-tag` `gql` to
105105
avoid stale values due to
106-
caching ([#109](https://github.com/aws/amazon-neptune-for-graphql/pull/109))
106+
caching ([#109](https://github.com/aws/amazon-neptune-for-graphql/pull/109))
107+
* Fixed nested edge subqueries with sorting to pass the edge variable so that it
108+
can be referenced further in the
109+
query ([#114](https://github.com/aws/amazon-neptune-for-graphql/pull/114))

src/test/templates/JSResolverOCHTTPS.test.js

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ test('should resolve app sync event with nested sort arguments', () => {
236236
expect(result).toEqual({
237237
query: 'MATCH (getNodeAirports_Airport:`airport`) WITH getNodeAirports_Airport ORDER BY getNodeAirports_Airport.desc ASC, getNodeAirports_Airport.code DESC\n' +
238238
'OPTIONAL MATCH (getNodeAirports_Airport)<-[getNodeAirports_Airport_airportRoutesIn_route:route]-(getNodeAirports_Airport_airportRoutesIn:`airport`) ' +
239-
'WITH getNodeAirports_Airport, getNodeAirports_Airport_airportRoutesIn ORDER BY getNodeAirports_Airport_airportRoutesIn.country ASC, getNodeAirports_Airport_airportRoutesIn.city DESC\n' +
239+
'WITH getNodeAirports_Airport, getNodeAirports_Airport_airportRoutesIn, getNodeAirports_Airport_airportRoutesIn_route ORDER BY getNodeAirports_Airport_airportRoutesIn.country ASC, getNodeAirports_Airport_airportRoutesIn.city DESC\n' +
240240
'WITH getNodeAirports_Airport, CASE WHEN getNodeAirports_Airport_airportRoutesIn IS NULL THEN [] ELSE COLLECT({country: getNodeAirports_Airport_airportRoutesIn.`country`, city: getNodeAirports_Airport_airportRoutesIn.`city`}) END AS getNodeAirports_Airport_airportRoutesIn_collect\n' +
241241
'RETURN collect({desc: getNodeAirports_Airport.`desc`, code: getNodeAirports_Airport.`code`, airportRoutesIn: getNodeAirports_Airport_airportRoutesIn_collect})',
242242
parameters: {},
@@ -269,7 +269,8 @@ test('should resolve app sync event with nested sort arguments and variables', (
269269

270270
expect(result).toEqual({
271271
query: 'MATCH (getNodeAirports_Airport:`airport`) WITH getNodeAirports_Airport ORDER BY getNodeAirports_Airport.country ASC, getNodeAirports_Airport.city ASC LIMIT 1\n' +
272-
'OPTIONAL MATCH (getNodeAirports_Airport)<-[getNodeAirports_Airport_airportRoutesIn_route:route]-(getNodeAirports_Airport_airportRoutesIn:`airport`) WITH getNodeAirports_Airport, getNodeAirports_Airport_airportRoutesIn ORDER BY getNodeAirports_Airport_airportRoutesIn.country DESC, getNodeAirports_Airport_airportRoutesIn.code DESC\n' +
272+
'OPTIONAL MATCH (getNodeAirports_Airport)<-[getNodeAirports_Airport_airportRoutesIn_route:route]-(getNodeAirports_Airport_airportRoutesIn:`airport`) ' +
273+
'WITH getNodeAirports_Airport, getNodeAirports_Airport_airportRoutesIn, getNodeAirports_Airport_airportRoutesIn_route ORDER BY getNodeAirports_Airport_airportRoutesIn.country DESC, getNodeAirports_Airport_airportRoutesIn.code DESC\n' +
273274
'WITH getNodeAirports_Airport, CASE WHEN getNodeAirports_Airport_airportRoutesIn IS NULL THEN [] ELSE COLLECT({_id:ID(getNodeAirports_Airport_airportRoutesIn), city: getNodeAirports_Airport_airportRoutesIn.`city`, code: getNodeAirports_Airport_airportRoutesIn.`code`, country: getNodeAirports_Airport_airportRoutesIn.`country`})[..1] END AS getNodeAirports_Airport_airportRoutesIn_collect\n' +
274275
'RETURN collect({_id:ID(getNodeAirports_Airport), city: getNodeAirports_Airport.`city`, code: getNodeAirports_Airport.`code`, country: getNodeAirports_Airport.`country`, airportRoutesIn: getNodeAirports_Airport_airportRoutesIn_collect})[..1]',
275276
parameters: {},
@@ -278,6 +279,40 @@ test('should resolve app sync event with nested sort arguments and variables', (
278279
});
279280
});
280281

282+
test('should resolve app sync event with nested sort and nested selection', () => {
283+
const result = resolveGraphDBQueryFromAppSyncEvent({
284+
field: 'getNodeAirports',
285+
arguments: {},
286+
variables: {
287+
nestedSort: [ { country: 'DESC'} ]
288+
},
289+
selectionSetGraphQL: '{\n' +
290+
' code\n' +
291+
' airportRoutesIn(sort: $nestedSort) {\n' +
292+
' code\n' +
293+
' route {\n' +
294+
' dist\n' +
295+
' }\n' +
296+
' }\n' +
297+
'}'
298+
});
299+
300+
expect(result).toEqual({
301+
query: 'MATCH (getNodeAirports_Airport:`airport`)\n' +
302+
'OPTIONAL MATCH (getNodeAirports_Airport)<-[getNodeAirports_Airport_airportRoutesIn_route:route]-(getNodeAirports_Airport_airportRoutesIn:`airport`) ' +
303+
'WITH getNodeAirports_Airport, getNodeAirports_Airport_airportRoutesIn, getNodeAirports_Airport_airportRoutesIn_route ' +
304+
'ORDER BY getNodeAirports_Airport_airportRoutesIn.country DESC\n' +
305+
'WITH getNodeAirports_Airport, getNodeAirports_Airport_airportRoutesIn, {dist: getNodeAirports_Airport_airportRoutesIn_route.`dist`} AS getNodeAirports_Airport_airportRoutesIn_route_one\n' +
306+
'WITH getNodeAirports_Airport, CASE WHEN getNodeAirports_Airport_airportRoutesIn IS NULL THEN [] ' +
307+
'ELSE COLLECT({code: getNodeAirports_Airport_airportRoutesIn.`code`, route: getNodeAirports_Airport_airportRoutesIn_route_one}) ' +
308+
'END AS getNodeAirports_Airport_airportRoutesIn_collect\n' +
309+
'RETURN collect({code: getNodeAirports_Airport.`code`, airportRoutesIn: getNodeAirports_Airport_airportRoutesIn_collect})',
310+
parameters: {},
311+
language: 'opencypher',
312+
refactorOutput: null
313+
});
314+
});
315+
281316
test('should resolve AppSync event with ID field as both top-level and nested sort argument', () => {
282317
const result = resolveGraphDBQueryFromAppSyncEvent({
283318
field: 'getNodeAirports',
@@ -295,7 +330,8 @@ test('should resolve AppSync event with ID field as both top-level and nested so
295330

296331
expect(result).toEqual({
297332
query: 'MATCH (getNodeAirports_Airport:`airport`) WITH getNodeAirports_Airport ORDER BY ID(getNodeAirports_Airport) ASC\n' +
298-
'OPTIONAL MATCH (getNodeAirports_Airport)<-[getNodeAirports_Airport_airportRoutesIn_route:route]-(getNodeAirports_Airport_airportRoutesIn:`airport`) WITH getNodeAirports_Airport, getNodeAirports_Airport_airportRoutesIn ORDER BY ID(getNodeAirports_Airport_airportRoutesIn) DESC\n' +
333+
'OPTIONAL MATCH (getNodeAirports_Airport)<-[getNodeAirports_Airport_airportRoutesIn_route:route]-(getNodeAirports_Airport_airportRoutesIn:`airport`) ' +
334+
'WITH getNodeAirports_Airport, getNodeAirports_Airport_airportRoutesIn, getNodeAirports_Airport_airportRoutesIn_route ORDER BY ID(getNodeAirports_Airport_airportRoutesIn) DESC\n' +
299335
'WITH getNodeAirports_Airport, CASE WHEN getNodeAirports_Airport_airportRoutesIn IS NULL THEN [] ELSE COLLECT({_id:ID(getNodeAirports_Airport_airportRoutesIn)}) END AS getNodeAirports_Airport_airportRoutesIn_collect\n' +
300336
'RETURN collect({_id:ID(getNodeAirports_Airport), airportRoutesIn: getNodeAirports_Airport_airportRoutesIn_collect})',
301337
parameters: {},

templates/JSResolverOCHTTPS.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,9 @@ function createTypeFieldStatementAndRecurse({selection, fieldSchemaInfo, lastNam
700700
const argsAndWhereClauses = extractQueryArgsAndWhereClauses(selection.arguments, fieldSchemaInfo);
701701
const queryArgs = argsAndWhereClauses.queryArguments?.length > 0 ? `{${argsAndWhereClauses.queryArguments.join(',')}}` : '';
702702
const whereClause = argsAndWhereClauses.whereClauses?.length > 0 ? ` WHERE ${argsAndWhereClauses.whereClauses.join(' AND ')}` : '';
703-
const orderByClause = fieldSchemaInfo.argOrderBy?.length ? ` WITH ${lastNamePath}, ${schemaTypeInfo.pathName} ORDER BY ${fieldSchemaInfo.argOrderBy.map(orderBy => `${orderBy.field === fieldSchemaInfo.graphDBIdArgName ? `ID(${schemaTypeInfo.pathName})` : `${schemaTypeInfo.pathName}.${orderBy.field}`} ${orderBy.direction}`).join(', ')}` : '';
703+
const edgePath = schemaTypeInfo.isRelationship ? `${schemaTypeInfo.pathName}_${schemaTypeInfo.relationship.edgeType}` : '';
704+
const withClause = `${[lastNamePath, schemaTypeInfo.pathName, edgePath].filter(path => path !== '').join(', ')}`;
705+
const orderByClause = fieldSchemaInfo.argOrderBy?.length ? ` WITH ${withClause} ORDER BY ${fieldSchemaInfo.argOrderBy.map(orderBy => `${orderBy.field === fieldSchemaInfo.graphDBIdArgName ? `ID(${schemaTypeInfo.pathName})` : `${schemaTypeInfo.pathName}.${orderBy.field}`} ${orderBy.direction}`).join(', ')}` : '';
704706

705707
if (schemaTypeInfo.isRelationship) {
706708
const arrows = ['<-', '-', '->'];

0 commit comments

Comments
 (0)