amplify-flutter
amplify-flutter copied to clipboard
GraphQL helper doesn't support query and mutation on the many-to-many connection models
Description
Hello everyone. After encountering a lot of problems about DataStore, I removed all DataStore and check realtime datas on AppSync from Amplify on Flutter. Anyways here's is the issue.
TL; DR: ModelQueries.list creating missing document
related schema:
type Department @model @auth(rules: [{allow: public, operations: [read], provider: iam}, {allow: private}]) {
id: ID!
nameEn: String!
nameTr: String!
university: University @belongsTo
mainStudents: [Student] @manyToMany(relationName: "MainDepartmentStudent")
students: [Student] @manyToMany(relationName: "DepartmentStudents")
mainTeachers: [Teacher] @manyToMany(relationName: "MainDepartmentTeachers")
teachers: [Teacher] @manyToMany(relationName: "DepartmentTeachers")
}
type Student @model @auth(rules: [{allow: private, operations: [create, read, update]}, {allow: owner}]) {
id: ID!
photo: String
phone: String
universityNumber: String!
email: String!
birthday: AWSDate!
gender: Gender!
cognitoId: ID!
internships: [Internship] @hasMany
company: Company @belongsTo
universityClass: UniversityClass
universityLevel: UniversityLevel
department: [Department] @manyToMany(relationName: "MainDepartmentStudent")
departments: [Department] @manyToMany(relationName: "DepartmentStudents")
}
That's my query, it should work here's is request:
Future getStudentDepartment() async {
try {
final departmentRequest = ModelQueries.list(
MainDepartmentStudent.classType,
where: MainDepartmentStudent.STUDENT
.eq(Get.find<AmplifyServices>().studentObj.value.id));
// GraphQLRequest<PaginatedResult<MainDepartmentStudent>> request =
// GraphQLRequest<PaginatedResult<MainDepartmentStudent>>(
// document: getStudentDepartmentQuery,
// variables: {
// 'student': Get.find<AmplifyServices>().studentObj.value.id,
// },
// decodePath: departmentRequest.decodePath,
// modelType: departmentRequest.modelType,
// );
print("TEEST: ${departmentRequest.variables}");
print("TEEST: ${departmentRequest.document}");
try {
final departmentResponse =
await Amplify.API.query(request: departmentRequest).response;
// Get student department
try {
final departmentRequest = ModelQueries.get(Department.classType,
departmentResponse.data!.items.first!.department.id);
try {
final departmentResponse =
await Amplify.API.query(request: departmentRequest).response;
studentDepartment = departmentResponse.data;
update();
debugPrint("ok.. found department");
} catch (e) {
print(e);
}
} catch (e) {
debugPrint("cannot get department trying again... 0 $e");
//await Future.delayed(const Duration(milliseconds: 100));
//return getStudentDepartment();
}
} catch (e) {
print(e);
}
} catch (e) {
debugPrint("cannot get student trying again... $e");
await Future.delayed(const Duration(milliseconds: 100));
return getStudentDepartment();
}
}
here's the response, error related to department is null:
GraphQL query operation succeeded with response : ["data": "{\"listMainDepartmentStudents\":{\"nextToken\":null,\"items\":[{\"id\":\"b5b3aaf5-f23d-47fc-bc58-c643f1ede4ff\",\"student\":{\"universityClass\":\"THIRD\",\"id\":\"dd1c140f-4d0e-4332-a511-e4ce015d0f53\",\"updatedAt\":\"2022-06-21T15:18:46.925Z\",\"phone\":\"\",\"photo\":\"\",\"universityNumber\":\"4554545\",\"cognitoId\":\"1e2667c5-480f-44f5-b657-87c316c0bee7\",\"birthday\":\"2022-06-15\",\"universityLevel\":\"ASSOCIATE\",\"createdAt\":\"2022-06-21T15:18:46.925Z\",\"gender\":\"MALE\",\"email\":\"[email protected]\"},\"updatedAt\":\"2022-06-21T15:18:47.204Z\",\"createdAt\":\"2022-06-21T15:18:47.204Z\"}]}}", "errors": []]
flutter: cannot get department trying again... 0 AmplifyCodeGenModelException(message: The field you are accessing is not nullable but has a null value. It was marked as required (!) in your schema.graphql but the containing model class was initialized without setting its value., recoverySuggestion: Please validate that the containing model class was initialized properly with all requried fields being initialized. This can happen when a nested model is returned but only its id field has been set, underlyingException: Null check operator used on a null value)
Let's investigate graphql document and variables: document:
variables: {filter: {studentID: {eq: dd1c140f-4d0e-4332-a511-e4ce015d0f53}}, limit: null, nextToken: null}
document:
query listMainDepartmentStudents($filter: ModelMainDepartmentStudentFilterInput, $limit: Int, $nextToken: String) {
listMainDepartmentStudents(filter: $filter, limit: $limit, nextToken: $nextToken) {
items {
id
createdAt
updatedAt
student {
id
photo
phone
universityNumber
email
birthday
gender
cognitoId
universityClass
universityLevel
createdAt
updatedAt
}
}
nextToken
}
}
As we can we, there's no department in the graphql document, that's the issue. ModelQueries.list should create department as I need.
So I tried to modify variable and create custom request like this. I didn't use original document to modify because on filter there is filter object and I didn't want to parse these:
Future getStudentDepartment() async {
try {
final departmentRequest = ModelQueries.list(
MainDepartmentStudent.classType,
where: MainDepartmentStudent.STUDENT
.eq(Get.find<AmplifyServices>().studentObj.value.id));
GraphQLRequest<PaginatedResult<MainDepartmentStudent>> request =
GraphQLRequest<PaginatedResult<MainDepartmentStudent>>(
document: """
query getStudentDepartment(\$studentID: ID = "") {
listMainDepartmentStudents(filter: {studentID: {eq: \$studentID}}) {
items {
id
department {
nameEn
nameTr
id
createdAt
universityDepartmentsId
updatedAt
university {
id
logo
managerIds
nameEn
nameTr
studentCount
supportMail
teacherCount
updatedAt
createdAt
}
}
student {
email
gender
birthday
cognitoId
companyStudentsId
createdAt
id
owner
phone
photo
universityClass
universityLevel
universityNumber
updatedAt
}
}
nextToken
}
}""",
variables: {
'studentID': Get.find<AmplifyServices>().studentObj.value.id,
},
decodePath: departmentRequest.decodePath,
modelType: departmentRequest.modelType,
);
print("TEEST: ${request.variables}");
print("TEEST: ${request.document}");
try {
final departmentResponse =
await Amplify.API.query(request: request).response;
// Get student department
try {
final departmentRequest = ModelQueries.get(Department.classType,
departmentResponse.data!.items.first!.department.id);
try {
final departmentResponse =
await Amplify.API.query(request: departmentRequest).response;
studentDepartment = departmentResponse.data;
update();
debugPrint("ok.. found department");
} catch (e) {
print(e);
}
} catch (e) {
debugPrint("cannot get department trying again... 0 $e");
//await Future.delayed(const Duration(milliseconds: 100));
//return getStudentDepartment();
}
} catch (e) {
print(e);
}
} catch (e) {
debugPrint("cannot get student trying again... $e");
await Future.delayed(const Duration(milliseconds: 100));
return getStudentDepartment();
}
}
and here's the variable and document:
variables: {studentID: dd1c140f-4d0e-4332-a511-e4ce015d0f53}
document:
listMainDepartmentStudents(filter: {studentID: {eq: $studentID}}) {
items {
id
department {
nameEn
nameTr
id
createdAt
universityDepartmentsId
updatedAt
university {
id
logo
managerIds
nameEn
nameTr
studentCount
supportMail
teacherCount
updatedAt
createdAt
}
}
student {
email
gender
birthday
cognitoId
companyStudentsId
createdAt
id
owner
phone
photo
universityClass
universityLevel
universityNumber
updatedAt
}
}
nextToken
}
}
and response:
GraphQL query operation succeeded with response : ["errors": [], "data": "{\"getDepartment\":{\"nameTr\":\"Any name\",\"id\":\"2a8b634e-43cf-4c13-ba74-a51e40355e3a\",\"nameEn\":\"Any name\",\"updatedAt\":\"2022-06-17T19:06:06.303Z\",\"university\":{\"studentCount\":1958,\"nameEn\":\"Any Name\",\"supportMail\":\"[email protected]\",\"id\":\"5166e729-abd8-4722-8a45-771c5b443744\",\"nameTr\":\"Any name\",\"updatedAt\":\"2022-06-13T18:13:45.221Z\",\"teacherCount\":243,\"managerIds\":null,\"createdAt\":\"2022-06-13T18:13:45.221Z\",\"logo\":\"\"},\"createdAt\":\"2022-06-17T19:06:06.303Z\"}}"]
flutter: ok.. found department
So it's succeed.
Categories
- [ ] Analytics
- [ ] API (REST)
- [X] API (GraphQL)
- [ ] Auth
- [ ] Authenticator
- [ ] DataStore
- [ ] Storage
Steps to Reproduce
No response
Screenshots
No response
Platforms
- [X] iOS
- [X] Android
Android Device/Emulator API Level
API 21
Environment
[✓] Flutter (Channel stable, 3.0.2, on macOS 12.4 21F79 darwin-x64, locale tr)
• Flutter version 3.0.2 at /Users/marlonjd/flutter/flutter2
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision cd41fdd495 (2 weeks ago), 2022-06-08 09:52:13 -0700
• Engine revision f15f824b57
• Dart version 2.17.3
• DevTools version 2.12.2
[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
• Android SDK at /Users/marlonjd/Library/Android/sdk
• Platform android-32, build-tools 32.0.0
• Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• CocoaPods version 1.11.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
[✓] VS Code (version 1.68.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.42.0
[✓] Connected device (3 available)
• FF iPod touch (mobile) • be3091413ece7869d08367bf2985276a1e125390 • ios • iOS 15.5 19F77
• macOS (desktop) • macos • darwin-x64 • macOS 12.4 21F79 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 103.0.5060.53
[✓] HTTP Host Availability
• All required HTTP hosts are available
• No issues found!
Dependencies
Dart SDK 2.17.3
Flutter SDK 3.0.2
monolibmobile 1.0.0+1
dependencies:
- amplify_analytics_pinpoint 0.6.0 [amplify_analytics_pinpoint_android amplify_analytics_pinpoint_ios amplify_core aws_common flutter meta]
- amplify_api 0.6.0 [amplify_api_android amplify_api_ios amplify_core amplify_flutter aws_common collection flutter meta plugin_platform_interface]
- amplify_auth_cognito 0.6.0 [amplify_auth_cognito_android amplify_auth_cognito_ios amplify_core aws_common collection flutter meta plugin_platform_interface]
- amplify_datastore 0.6.0 [flutter amplify_datastore_plugin_interface amplify_core plugin_platform_interface meta collection async]
- amplify_flutter 0.6.0 [amplify_core amplify_datastore_plugin_interface amplify_flutter_android amplify_flutter_ios aws_common collection flutter meta plugin_platform_interface]
- amplify_storage_s3 0.6.0 [amplify_storage_s3_android amplify_storage_s3_ios amplify_core aws_common meta flutter plugin_platform_interface]
- app_tutorial 0.3.2 [flutter_staggered_grid_view flutter]
- cached_network_image 3.2.1 [flutter flutter_cache_manager octo_image cached_network_image_platform_interface cached_network_image_web]
- card_swiper 2.0.4 [flutter]
- cloud_firestore 3.1.17 [cloud_firestore_platform_interface cloud_firestore_web collection firebase_core firebase_core_platform_interface flutter meta]
- cupertino_icons 1.0.4
- file_picker 3.0.4 [flutter flutter_web_plugins flutter_plugin_android_lifecycle plugin_platform_interface]
- firebase_analytics 9.1.9 [firebase_analytics_platform_interface firebase_analytics_web firebase_core firebase_core_platform_interface flutter]
- firebase_auth 3.3.19 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta]
- firebase_core 1.17.1 [firebase_core_platform_interface firebase_core_web flutter meta]
- firebase_messaging 11.4.1 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta]
- firebase_storage 10.2.17 [firebase_core firebase_core_platform_interface firebase_storage_platform_interface firebase_storage_web flutter]
- flutter 0.0.0 [characters collection material_color_utilities meta vector_math sky_engine]
- flutter_cache_manager 3.3.0 [clock collection file flutter http path path_provider pedantic rxdart sqflite uuid]
- flutter_chat_types 3.3.4 [equatable json_annotation meta]
- flutter_chat_ui 1.5.8 [flutter diffutil_dart equatable flutter_chat_types flutter_link_previewer flutter_parsed_text intl meta photo_view url_launcher visibility_detector]
- flutter_custom_carousel_slider 1.2.0 [flutter]
- flutter_firebase_chat_core 1.5.4 [flutter cloud_firestore firebase_auth firebase_core flutter_chat_types meta]
- flutter_local_notifications 9.5.3+1 [clock flutter flutter_local_notifications_linux flutter_local_notifications_platform_interface timezone]
- flutter_localizations 0.0.0 [flutter intl characters clock collection material_color_utilities meta path vector_math]
- flutter_mailer 2.0.1 [flutter]
- geo 0.3.0 [meta]
- get 4.6.5 [flutter]
- get_storage 2.0.3 [flutter get path_provider]
- getwidget 3.0.1 [flutter]
- http 0.13.4 [async http_parser meta path]
- image_picker 0.8.5+3 [flutter image_picker_android image_picker_for_web image_picker_ios image_picker_platform_interface]
- intl 0.17.0 [clock path]
- loader_overlay 2.0.7 [flutter back_button_interceptor]
- location 4.4.0 [flutter location_platform_interface location_web]
- material_design_icons_flutter 5.0.6595 [flutter]
- mime 1.0.2
- open_file 3.2.1 [flutter ffi]
- path_provider 2.0.10 [flutter path_provider_android path_provider_ios path_provider_linux path_provider_macos path_provider_platform_interface path_provider_windows]
- qr_flutter 4.0.0 [flutter qr]
- rive 0.9.0 [collection flutter graphs http meta]
- stories_for_flutter 1.2.0 [flutter flutter_web_plugins]
transitive dependencies:
- amplify_analytics_pinpoint_android 0.6.0 [flutter]
- amplify_analytics_pinpoint_ios 0.6.0 [flutter]
- amplify_api_android 0.6.0 [flutter]
- amplify_api_ios 0.6.0 [amplify_core flutter]
- amplify_auth_cognito_android 0.6.0 [flutter]
- amplify_auth_cognito_ios 0.6.0 [amplify_core flutter]
- amplify_core 0.6.0 [aws_common collection flutter intl json_annotation meta plugin_platform_interface uuid]
- amplify_datastore_plugin_interface 0.6.0 [amplify_core collection flutter meta]
- amplify_flutter_android 0.6.0 [flutter]
- amplify_flutter_ios 0.6.0 [amplify_core flutter]
- amplify_storage_s3_android 0.6.0 [flutter]
- amplify_storage_s3_ios 0.6.0 [flutter]
- args 2.3.1
- async 2.8.2 [collection meta]
- aws_common 0.1.1 [async collection http meta stream_transform uuid]
- back_button_interceptor 6.0.0 [collection flutter]
- cached_network_image_platform_interface 1.0.0 [flutter flutter_cache_manager]
- cached_network_image_web 1.0.1 [flutter flutter_cache_manager cached_network_image_platform_interface]
- characters 1.2.0
- charcode 1.3.1
- clock 1.1.0
- cloud_firestore_platform_interface 5.5.7 [collection firebase_core flutter meta plugin_platform_interface]
- cloud_firestore_web 2.6.16 [cloud_firestore_platform_interface collection firebase_core firebase_core_web flutter flutter_web_plugins js]
- collection 1.16.0
- cross_file 0.3.3+1 [js meta]
- crypto 3.0.2 [typed_data]
- csslib 0.17.2 [source_span]
- dbus 0.7.4 [args ffi meta xml]
- diffutil_dart 3.0.0
- equatable 2.0.3 [collection meta]
- ffi 1.2.1
- file 6.1.2 [meta path]
- firebase_analytics_platform_interface 3.1.7 [firebase_core flutter meta plugin_platform_interface]
- firebase_analytics_web 0.4.0+14 [firebase_analytics_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins js]
- firebase_auth_platform_interface 6.2.7 [firebase_core flutter meta plugin_platform_interface]
- firebase_auth_web 3.3.16 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser intl js meta]
- firebase_core_platform_interface 4.4.0 [collection flutter meta plugin_platform_interface]
- firebase_core_web 1.6.4 [firebase_core_platform_interface flutter flutter_web_plugins js meta]
- firebase_messaging_platform_interface 3.5.1 [firebase_core flutter meta plugin_platform_interface]
- firebase_messaging_web 2.4.1 [firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins js meta]
- firebase_storage_platform_interface 4.1.7 [collection firebase_core flutter meta plugin_platform_interface]
- firebase_storage_web 3.2.16 [async firebase_core firebase_core_web firebase_storage_platform_interface flutter flutter_web_plugins http js meta]
- flutter_blurhash 0.7.0 [flutter]
- flutter_link_previewer 2.6.6 [flutter flutter_chat_types flutter_linkify html http linkify meta url_launcher]
- flutter_linkify 5.0.2 [flutter linkify]
- flutter_local_notifications_linux 0.4.2 [flutter flutter_local_notifications_platform_interface dbus path xdg_directories]
- flutter_local_notifications_platform_interface 5.0.0 [flutter plugin_platform_interface]
- flutter_parsed_text 2.2.1 [flutter]
- flutter_plugin_android_lifecycle 2.0.6 [flutter]
- flutter_staggered_grid_view 0.4.1 [flutter]
- flutter_web_plugins 0.0.0 [flutter js characters collection material_color_utilities meta vector_math]
- graphs 2.1.0 [collection]
- html 0.15.0 [csslib source_span]
- http_parser 4.0.1 [collection source_span string_scanner typed_data]
- image_picker_android 0.8.5 [flutter flutter_plugin_android_lifecycle image_picker_platform_interface]
- image_picker_for_web 2.1.8 [flutter flutter_web_plugins image_picker_platform_interface]
- image_picker_ios 0.8.5+5 [flutter image_picker_platform_interface]
- image_picker_platform_interface 2.5.0 [cross_file flutter http plugin_platform_interface]
- js 0.6.4
- json_annotation 4.5.0 [meta]
- linkify 4.1.0
- location_platform_interface 2.3.0 [flutter meta plugin_platform_interface]
- location_web 3.1.1 [flutter flutter_web_plugins http_parser js location_platform_interface meta]
- material_color_utilities 0.1.4
- meta 1.7.0
- octo_image 1.0.2 [flutter flutter_blurhash]
- path 1.8.1
- path_provider_android 2.0.14 [flutter path_provider_platform_interface]
- path_provider_ios 2.0.9 [flutter path_provider_platform_interface]
- path_provider_linux 2.1.7 [ffi flutter path path_provider_platform_interface xdg_directories]
- path_provider_macos 2.0.6 [flutter path_provider_platform_interface]
- path_provider_platform_interface 2.0.4 [flutter platform plugin_platform_interface]
- path_provider_windows 2.0.7 [ffi flutter path path_provider_platform_interface win32]
- pedantic 1.11.1
- petitparser 5.0.0 [meta]
- photo_view 0.13.0 [flutter]
- platform 3.1.0
- plugin_platform_interface 2.1.2 [meta]
- process 4.2.4 [file path platform]
- qr 2.1.0 [meta]
- rxdart 0.27.4
- sky_engine 0.0.99
- source_span 1.8.2 [collection path term_glyph]
- sqflite 2.0.2+1 [flutter sqflite_common path]
- sqflite_common 2.2.1+1 [synchronized path meta]
- stream_transform 2.0.0
- string_scanner 1.1.0 [charcode source_span]
- synchronized 3.0.0+2
- term_glyph 1.2.0
- timezone 0.8.0 [path]
- typed_data 1.3.1 [collection]
- url_launcher 6.1.2 [flutter url_launcher_android url_launcher_ios url_launcher_linux url_launcher_macos url_launcher_platform_interface url_launcher_web url_launcher_windows]
- url_launcher_android 6.0.17 [flutter url_launcher_platform_interface]
- url_launcher_ios 6.0.17 [flutter url_launcher_platform_interface]
- url_launcher_linux 3.0.1 [flutter url_launcher_platform_interface]
- url_launcher_macos 3.0.1 [flutter url_launcher_platform_interface]
- url_launcher_platform_interface 2.0.5 [flutter plugin_platform_interface]
- url_launcher_web 2.0.11 [flutter flutter_web_plugins url_launcher_platform_interface]
- url_launcher_windows 3.0.1 [flutter url_launcher_platform_interface]
- uuid 3.0.6 [crypto]
- vector_math 2.1.2
- visibility_detector 0.2.2 [flutter]
- win32 2.6.1 [ffi]
- xdg_directories 0.2.0+1 [meta path process]
- xml 6.1.0 [collection meta petitparser]
Device
iPod Touch 7
OS
iOS 15.5
CLI Version
9.0.0
Additional Context
No response
Hi @MarlonJD thank you for posting your issue and providing a detailed explanation of what you did.
It appears you are trying to access the Department field on your Student object.
We do not load the fields (except id) for nested models. The Student object has a Department field. The Department field is a nested model so we do not load all fields of that object. In the error message you received:
Please validate that the containing model class was initialized properly with all requried fields being initialized. **This can happen when a nested model is returned but only its id field has been set**
Instead, you can use the Department object's id field to make another query for the full Department object.
Apologies this wasn't clear in the beginning. We'll look internally into how we might improve documentation regarding this behavior.
Yes i understand what you mean but this isn't the solution because there is no department id in response. That's the issue. We can add access nested object if it's first level on Amplify.API, so there is no nested object issue in here. İssue is in the graphql document that using for the query. İf there was departmentID it could be. And student already becoming readable and also nested. So i don't think it is nested object issue.
Thanks for the clarification @MarlonJD we'll take a further look. The issue appears to be with nested model behavior and how to query for relationships of manyToMany
. Further note, the connected models have different access permissions.
Hello @MarlonJD
Thanks for reporting this issue and providing the details.
As we can we, there's no department in the graphql document, that's the issue. ModelQueries.list should create department as I need.
I did some testing, I can see the API GraphQL helper currently supporting only generating GraphQL document with 1 belongsTo
associated model. In your use case, the generated many-to-many connection model MainDepartmentStudent
has two belongsTo
associated models Department
and Student
. This cause two issues:
- Using API GraphQL to save record
MainDepartmentStudent
will fail, as it cannot provide eitherdepartmentId
studentId
- Using API GraphQL to query record
MainDepartmentStudent
will missing selection set of one of the nested models
As GraphQL helper rolled out prior to Amplify GraphQL Transformer v2, it looks like we have a function disparity now. I will mark this issue as a feature request to follow up.
As a workaround, please continually create GraphQL document manually. Sorry for the inconvenience.
Also -
After encountering a lot of problems about DataStore, I removed all DataStore
Sorry that you encounter issues with DataStore, would you mind to share them with us, and to see how can we help? (I searched but seems that you haven't reported any issues around DataStore yet)
Hello @MarlonJD
Thanks for reporting this issue and providing the details.
As we can we, there's no department in the graphql document, that's the issue. ModelQueries.list should create department as I need.
I did some testing, I can see the API GraphQL helper currently supporting only generating GraphQL document with 1
belongsTo
associated model. In your use case, the generated many-to-many connection modelMainDepartmentStudent
has twobelongsTo
associated modelsDepartment
andStudent
. This cause two issues:
- Using API GraphQL to save record
MainDepartmentStudent
will fail, as it cannot provide eitherdepartmentId
studentId
- Using API GraphQL to query record
MainDepartmentStudent
will missing selection set of one of the nested modelsAs GraphQL helper rolled out prior to Amplify GraphQL Transformer v2, it looks like we have a function disparity now. I will mark this issue as a feature request to follow up.
As a workaround, please continually create GraphQL document manually. Sorry for the inconvenience.
Also -
After encountering a lot of problems about DataStore, I removed all DataStore
Sorry that you encounter issues with DataStore, would you mind to share them with us, and to see how can we help? (I searched but seems that you haven't reported any issues around DataStore yet)
Hey thanks for you detailed answer. First of all, we need to fix graphql request creation or something like fullRequest: true parameter and make query with all fields included nested models. On datastore side, i've been issued about public permissions and 2 belongsTo or ManyToMany fields cannot be get or saved. Now after i created ManyToMany fields i cannot even datastore sync anymore, so i needed to remove all datastore from my code, #1736 here is my datastore issue about permission issue. There is so much problem which we cannot modify query on datastore.
Thanks for the follow up @MarlonJD I'll find some time to test the datastore issue you described.
Hello @MarlonJD
Thanks for reporting this issue and providing the details.
As we can we, there's no department in the graphql document, that's the issue. ModelQueries.list should create department as I need.
I did some testing, I can see the API GraphQL helper currently supporting only generating GraphQL document with 1
belongsTo
associated model. In your use case, the generated many-to-many connection modelMainDepartmentStudent
has twobelongsTo
associated modelsDepartment
andStudent
. This cause two issues:
- Using API GraphQL to save record
MainDepartmentStudent
will fail, as it cannot provide eitherdepartmentId
studentId
- Using API GraphQL to query record
MainDepartmentStudent
will missing selection set of one of the nested modelsAs GraphQL helper rolled out prior to Amplify GraphQL Transformer v2, it looks like we have a function disparity now. I will mark this issue as a feature request to follow up.
As a workaround, please continually create GraphQL document manually. Sorry for the inconvenience.
Also -
After encountering a lot of problems about DataStore, I removed all DataStore
Sorry that you encounter issues with DataStore, would you mind to share them with us, and to see how can we help? (I searched but seems that you haven't reported any issues around DataStore yet)
hey @HuiSF is that really true? I have a relationship that I believe has two @belongsto relationships yet I am able to save both succesfully:
type Session @model @auth( rules: [ { allow: public } { allow: owner } { allow: groups, groups: ["Admin"] } ] ) { id: ID! name: String numPeoplePresent: Int notes: String eIdReader: String weighTiming: String cows: [Cow] @manyToMany(relationName: "CowSession") proceduresID: ID procedures: Procedures @hasOne(fields: ["proceduresID"]) }
yet the only time I struggle is when I try to query the nested relationship. I know it works because I tested it on the graphQL console provided by amplify:
This works locally:
String graphQLDocument = '''query getSession(\$id: ID!) { $getSession(id: \$id) { numPeoplePresent notes name eIdReader id owner proceduresID updatedAt weighTiming } }''';
but this breaks:
String graphQLDocument = '''query getSession(\$id: ID!) { $getSession(id: \$id) { numPeoplePresent notes. name. eIdReader id owner proceduresID updatedAt weighTiming cows { items { cow { RfId } } } } }''';
any idea why?
Hi @RikiZimbakov can you please share the graphql schema you're using?
Hello @MarlonJD
Thanks for reporting this issue and providing the details.
As we can we, there's no department in the graphql document, that's the issue. ModelQueries.list should create department as I need.
I did some testing, I can see the API GraphQL helper currently supporting only generating GraphQL document with 1
belongsTo
associated model. In your use case, the generated many-to-many connection modelMainDepartmentStudent
has twobelongsTo
associated modelsDepartment
andStudent
. This cause two issues:
- Using API GraphQL to save record
MainDepartmentStudent
will fail, as it cannot provide eitherdepartmentId
studentId
- Using API GraphQL to query record
MainDepartmentStudent
will missing selection set of one of the nested modelsAs GraphQL helper rolled out prior to Amplify GraphQL Transformer v2, it looks like we have a function disparity now. I will mark this issue as a feature request to follow up.
As a workaround, please continually create GraphQL document manually. Sorry for the inconvenience.
Also -
After encountering a lot of problems about DataStore, I removed all DataStore
Sorry that you encounter issues with DataStore, would you mind to share them with us, and to see how can we help? (I searched but seems that you haven't reported any issues around DataStore yet)
hey @HuiSF is that really true? I have a relationship that I believe has two @belongsto relationships yet I am able to save both succesfully:
type Session @model @auth( rules: [ { allow: public } { allow: owner } { allow: groups, groups: ["Admin"] } ] ) { id: ID! name: String numPeoplePresent: Int notes: String eIdReader: String weighTiming: String cows: [Cow] @manyToMany(relationName: "CowSession") proceduresID: ID procedures: Procedures @hasOne(fields: ["proceduresID"]) }
yet the only time I struggle is when I try to query the nested relationship. I know it works because I tested it on the graphQL console provided by amplify: This works locally:String graphQLDocument = '''query getSession(\$id: ID!) { $getSession(id: \$id) { numPeoplePresent notes name eIdReader id owner proceduresID updatedAt weighTiming } }''';
but this breaks:String graphQLDocument = '''query getSession(\$id: ID!) { $getSession(id: \$id) { numPeoplePresent notes. name. eIdReader id owner proceduresID updatedAt weighTiming cows { items { cow { RfId } } } } }''';
any idea why?
Thank you for all detailed answer. Same scheme and i just cannot sync datastore. İt's giving me error, when anything has 2 belongsTo even it's manyToMany. I tried to modify add all belongsTo but Json is malformed before there. Maybe i have to modify android/iOS library instead of flutter. I'll try to dig in again
@fjnoyp - Feel free to check out issue #2073 for a simple schema to replicate the issue. @haverchuck was kind enough to link my ticket to this issue.
As this has been a showstopper for my team and client, we dug further into the issue. I've found that inside of the graphql_request_factory.dart, when the request gets inside of buildInputVariableForMutations
function, it attempts to gather the belongsTo fields by calling the getBelongsToFieldFromModelSchema
function to get details around the field marked as belongsTo. The getBelongsToFieldFromModelSchema function:
ModelField? getBelongsToFieldFromModelSchema(ModelSchema modelSchema) {
return _getRelatedFields(modelSchema).singleFields.firstWhereOrNull((entry) =>
entry.association?.associationType == ModelAssociationEnum.BelongsTo);
}
As you can see, it calls firstWhereOrNull
on the fields which will only select the FIRST field that has a belongsTo annotation. After the getBelongsToFieldFromModelSchema
is called from the buildInputVariableForMutations
function, the next step that is performed is the REMOVAL of any fields that is deemed to be readonly or purely relational fields:
// Remove any relational fields or readonly.
Set<String> fieldsToRemove = schema.fields!.entries
.where((entry) =>
entry.value.association != null || entry.value.isReadOnly)
.map((entry) => entry.key)
.toSet();
What I'm not sure of, is how the fields are being selected for removal, since the entry.value.association SHOULD be ModelAssociationEnum.BelongsTo
, instead of null causing the field to be skipped (or at least I would think).
This is where I believe the fields are being removed causing the issue related to this ticket. From what I can see, it doesn't appear multiple belongsTo on a single model was ever implemented.
Hopefully this information helps the team drive towards a hastened delivery of the solution. If this is duplicative information that the team was already aware of...don't mind me and Carry On! :)
Hi @ignitum-ryan thanks for your great insights here! Yes the firstWhereOrNull
call is the root cause of this error. And yes you're right this was an oversight and not implemented. We are working on this now.
thanks to @fjnoyp. He fixed this issue. with #2087 and it's released on 0.6.9