I need to understand the logic of the method with which GraphQL operates a query. In a react application, I have the following code:
export const fetchPatientsChatMessages = async (
partitionKey: string,
sortKey: string
) => {
const client = generateClient();
const response = await client.graphql({
query: getPatientsChatMessages,
variables: {
limit: 163,
filter: {
and: [
{ PK: { eq: partitionKey } },
{ SK: { beginsWith: generateSortKey("CASE", sortKey, "APP") } },
{ SK: { contains: "CHAT" } },
],
},
},
});
return (response as GraphQlResponseList<ChatMessage>).data.listMains.items;
};
...and getPatientsChatMessages has the following structure:
export const getPatientsChatMessages = /* GraphQL */ `
query ListMains(
$PK: ID
$SK: ModelStringKeyConditionInput
$filter: ModelMainFilterInput
$limit: Int
$nextToken: String
$sortDirection: ModelSortDirection
) {
listMains(
PK: $PK
SK: $SK
filter: $filter
limit: $limit
nextToken: $nextToken
sortDirection: $sortDirection
) {
items {
PK
SK
DateTime
Sender
Message
}
nextToken
__typename
}
}
`;
The situation in the database table, I am accessing, is as follows: Total number of records: 195 , number of records with the partitionkey I am using in the fetch above: 24. I would expect that this instruction (since it is a query and not a scan), will limit its fetch process to the scope of the 24 records with the the partitionkey. But it obviously does not because: When the limit which I have set for test purpose above is below 163, no records are delivered. It appears that GraphQL scans over the entire table. In case the limit parameter is omitted, there is also no result since the system default value is even smaller. Is this behaviour of GraphQL "by design" or is it more likely that something in my database (DynamoDB) is fundamentally wrong? If it is "by design", I do not understand this concept - perhaps someone can explain. What should be the merit of a partitionkey when the system scans all records anyways when the data are fetched with a query?
I am using Amplify to work with the underlying DynamoDB. The relevant resolver codes are generated and not modified by me. Here is the resolver code I find for ListMains:
## [Start] List Request. **
#set( $args = $util.defaultIfNull($ctx.stash.transformedArgs,
$ctx.args) )
#set( $limit = $util.defaultIfNull($args.limit, 100) )
#set( $ListRequest = {
"version": "2018-05-29",
"limit": $limit
} )
#if( $args.nextToken )
#set( $ListRequest.nextToken = $args.nextToken )
#end
#if( !$util.isNullOrEmpty($ctx.stash.authFilter) )
#set( $filter = $ctx.stash.authFilter )
#if( !$util.isNullOrEmpty($args.filter) )
#set( $filter = {
"and": [$filter, $args.filter]
} )
#end
#else
#if( !$util.isNullOrEmpty($args.filter) )
#set( $filter = $args.filter )
#end
#end
#if( !$util.isNullOrEmpty($filter) )
#set( $filterExpression =
$util.parseJson($util.transform.toDynamoDBFilterExpression
($filter)) )
#if( $util.isNullOrEmpty($filterExpression) )
$util.error("Unable to process the filter expression",
"Unrecognized Filter")
#end
#if( !$util.isNullOrBlank($filterExpression.expression) )
#if( $filterExpression.expressionValues.size() == 0 )
$util.qr($filterExpression.remove("expressionValues"))
#end
#set( $ListRequest.filter = $filterExpression )
#end
#end
#if( !$util.isNull($ctx.stash.modelQueryExpression) &&
!$util.isNullOrEmpty($ctx.stash.
modelQueryExpression.expression) )
$util.qr($ListRequest.put("operation", "Query"))
$util.qr($ListRequest.put("query",
$ctx.stash.modelQueryExpression))
#if( !$util.isNull($args.sortDirection) &&
$args.sortDirection == "DESC" )
#set( $ListRequest.scanIndexForward = false )
#else
#set( $ListRequest.scanIndexForward = true )
#end
#else
$util.qr($ListRequest.put("operation", "Scan"))
#end
#if( !$util.isNull($ctx.stash.metadata.index) )
#set( $ListRequest.IndexName = $ctx.stash.metadata.index )
#end
$util.toJson($ListRequest)
## [End]
We can see that there is default limit of 100 but based on my understanding I can overwrite it to the limit parameter in my query definition above (here 163 for test purpose). But I do not understand the VTL code well enough to derive an answer to my principle question about the scope of records which are considered for the query and whether the partitionkey plays any role here.