[Gen2] dynamodb error when having optional sortkeys
Description
If making a field as sortKey in secondaryIndex and making the field optional, we are not able to submit a create request without specifying the value of this field.
Categories
- [ ] Analytics
- [ ] API (REST)
- [X] API (GraphQL)
- [ ] Auth
- [ ] Authenticator
- [X] DataStore
- [ ] Notifications (Push)
- [ ] Storage
Steps to Reproduce
- For any model, add secondary index like this:
Message: a
.model({
roomId: a.id().required(),
room: a.belongsTo('Room', 'roomId'),
createdAt: a.string(),
}).secondaryIndexes(index => [index('roomId').sortKeys(['createdAt']).queryField('listByDate')])
- Then submit a request to create a message (without specify
createAtvalue since it should be created by backend):
final newMessage = Message(room: room);
final request = ModelMutations.create(newMessage);
final response = await Amplify.API.mutate(request: request).response;
- Then it will show error
One or more parameter values were invalid: Type mismatch for Index Key createdAt Expected, I noticed this is becausecreateAthas a value null in request.variables['input'] instead of just ignoring it
What I want to do is just to sort messages by createAt date, this is one of the bug I found during the attempts. Not sure if it is the correct way.
Screenshots
No response
Platforms
- [ ] iOS
- [ ] Android
- [ ] Web
- [ ] macOS
- [ ] Windows
- [ ] Linux
Flutter Version
3.19.3
Amplify Flutter Version
2.0.0
Deployment Method
Amplify CLI
Schema
No response
Hello @hangoocn thank you for submitting this issue. We will look into this and get back to you!
Hello @hangoocn sorry for the delay in our response, but we are still investigating the best way to handle overriding Amplify generated fields in the schema. In the meantime we recommend setting the createdAt field client side or customizing your mutation to omit createdAt:
final room = Room();
final newMessage = Message(room: room, name: 'name');
var request = ModelMutations.create(newMessage);
request = request.copyWith(
variables: {
'input': {'name': 'test message', 'roomId': room.id} // omit createdAt
},
);
if you still need help sorting messages by createdAt for a specific roomId then the following code can help you manually generate a GraphQLRequest:
enum SortDirection {
asc('ASC'),
desc('DESC');
const SortDirection(this.graphQLValue);
final String graphQLValue;
}
GraphQLRequest<PaginatedResult<Message>> messagesByRoomIdAndCreatedAt({
required Room room,
SortDirection sortDirection = SortDirection.desc,
int? limit,
}) {
return GraphQLRequest<PaginatedResult<Message>>(
document: '''query listByDate(
\$roomId: ID!,
\$createdAt: ModelStringKeyConditionInput,
\$sortDirection: ModelSortDirection,
\$filter: ModelMessageFilterInput,
\$limit: Int,
\$nextToken: String
) {
listByDate(
roomId: \$roomId,
createdAt: \$createdAt,
sortDirection: \$sortDirection,
filter: \$filter,
limit: \$limit,
nextToken: \$nextToken
) {
items { id createdAt updatedAt room { roomId name createdAt updatedAt owner } roomId owner }
nextToken
}
}''',
modelType: const PaginatedModelType(Message.classType),
variables: <String, dynamic>{
'roomId': room.roomId,
'createdAt': null,
'sortDirection': sortDirection.graphQLValue,
'filter': null,
'limit': limit,
'nextToken': null,
},
decodePath: 'listByDate',
);
}
You will have to update the items {} to match the fields in your model. The messagesByRoomIdAndCreatedAt helper function can then be used like this:
var request = messagesByRoomIdAndCreatedAt(
room: someRoom,
sortDirection: SortDirection.desc,
);
final response = await Amplify.API.query(request: request).response;
final messages = response.data?.items;
Thanks @tyllark, I am using similar approach to overide the request before sending the request, so can customize the document or variables to anything we want.
Looking forward to a more standard way of doing that.